1. 程式人生 > >subprocess模組總結

subprocess模組總結

subprocess意在替代其他幾個老的模組或者函式,比如:os.system os.spawn* os.popen* popen2.* commands.*
subprocess最簡單的用法就是呼叫shell命令了,另外也可以呼叫程式,並且可以通過stdout,stdin和stderr進行互動。

subprocess的主類

subprocess.Popen(
      args,
      bufsize=0,
      executable=None,
      stdin=None,
      stdout=None,
      stderr=None,
      preexec_fn=None,
      close_fds=False,
      shell=False,
      cwd=None,
      env=None,
      universal_newlines=False,
      startupinfo=None,
      creationflags=0)

1)、args可以是字串或者序列型別(如:list,元組),用於指定程序的可執行檔案及其引數。如果是序列型別,第一個元素通常是可執行檔案的路徑。我們也可以顯式的使用executeable引數來指定可執行檔案的路徑。

2)、bufsize:指定緩衝。0 無緩衝,1 行緩衝,其他 緩衝區大小,負值 系統緩衝(全緩衝)

3)、stdin, stdout, stderr分別表示程式的標準輸入、輸出、錯誤控制代碼。他們可以是PIPE,檔案描述符或檔案物件,也可以設定為None,表示從父程序繼承。

4)、preexec_fn只在Unix平臺下有效,用於指定一個可執行物件(callable object),它將在子程序執行之前被呼叫。

5)、Close_sfs:在windows平臺下,如果close_fds被設定為True,則新建立的子程序將不會繼承父程序的輸入、輸出、錯誤管道。我們不能將close_fds設定為True同時重定向子程序的標準輸入、輸出與錯誤(stdin, stdout, stderr)。

6)、shell設為true,程式將通過shell來執行。

7)、cwd用於設定子程序的當前目錄

8)、env是字典型別,用於指定子程序的環境變數。如果env = None,子程序的環境變數將從父程序中繼承。
Universal_newlines:不同作業系統下,文字的換行符是不一樣的。如:windows下用'/r/n'表示換,而Linux下用'/n'。如果將此引數設定為True,Python統一把這些換行符當作'/n'來處理。startupinfo與createionflags只在windows下用效,它們將被傳遞給底層的CreateProcess()函式,用於設定子程序的一些屬性,如:主視窗的外觀,程序的優先順序等等。

9)、startupinfo與createionflags只在windows下有效,它們將被傳遞給底層的CreateProcess()函式,用於設定子程序的一些屬性,如:主視窗的外觀,程序的優先順序等等。

Popen方法

1)、Popen.poll():用於檢查子程序是否已經結束。設定並返回returncode屬性。

2)、Popen.wait():等待子程序結束。設定並返回returncode屬性。

3)、Popen.communicate(input=None):與子程序進行互動。向stdin傳送資料,或從stdout和stderr中讀取資料。可選引數input指定傳送到子程序的引數。Communicate()返回一個元組:(stdoutdata, stderrdata)。注意:如果希望通過程序的stdin向其傳送資料,在建立Popen物件的時候,引數stdin必須被設定為PIPE。同樣,如果希望從stdout和stderr獲取資料,必須將stdout和stderr設定為PIPE。

4)、Popen.send_signal(signal):向子程序傳送訊號。

5)、Popen.terminate():停止(stop)子程序。在windows平臺下,該方法將呼叫Windows API TerminateProcess()來結束子程序。

6)、Popen.kill():殺死子程序。

7)、Popen.stdin:如果在建立Popen物件是,引數stdin被設定為PIPE,Popen.stdin將返回一個檔案物件用於策子程序傳送指令。否則返回None。

8)、Popen.stdout:如果在建立Popen物件是,引數stdout被設定為PIPE,Popen.stdout將返回一個檔案物件用於策子程序傳送指令。否則返回None。

9)、Popen.stderr:如果在建立Popen物件是,引數stdout被設定為PIPE,Popen.stdout將返回一個檔案物件用於策子程序傳送指令。否則返回None。

10)、Popen.pid:獲取子程序的程序ID。

11)、Popen.returncode:獲取程序的返回值。如果程序還沒有結束,返回None。

12)、subprocess.call(*popenargs, **kwargs):執行命令。該函式將一直等待到子程序執行結束,並返回程序的returncode。文章一開始的例子就演示了call函式。如果子程序不需要進行互動,就可以使用該函式來建立。

13)、subprocess.check_call(*popenargs, **kwargs):與subprocess.call(*popenargs, **kwargs)功能一樣,只是如果子程序返回的returncode不為0的話,將觸發CalledProcessError異常。在異常物件中,包括程序的returncode資訊。

在程式中執行其他程式或shell

可以這樣寫
subprocess.Popen('指令碼/shell', shell=True)

也可以這樣
subprocess.call('指令碼/shell', shell=True)
兩者的區別是前者無阻塞,會和主程式並行執行,後者必須等待命令執行完畢,如果想要前者程式設計阻塞

可以這樣
s = subprocess.Popen('指令碼/shell', shell=True)
s.wait()

程式返回執行結果

有時候我們需要程式的返回結果,可以這樣做。
>>> s = subprocess.Popen('ls -l', shell=True, stdout=subprocess.PIPE)
>>> stdoutdata, stderrdata=s.communicate()
('\xe6\x80\xbb\xe7\x94\xa8\xe9\x87\x8f 152\n-rw------- 1 limbo limbo   808  7\xe6\x9c\x88  6 17:46 0000-00-00-welcome-to-jekyll.markdown.erb\ndrwx------ 2 limbo limbo  4096  8\xe6\x9c\x88 15 18:43 arg\ndrwx------ 2 limbo limbo  4096  8\xe6\x9c\x88  7 17:37 argv\ndrwxrwxr-x 2 limbo limbo  4096  9\xe6\x9c\x88 10 15:27 c\ndrwxrwxr-x 3 limbo limbo  4096  9\xe6\x9c\x88 11 14:35 d3\ndrwxrwxr-x 3 limbo limbo  4096  9\xe6\x9n', None)

它會返回一個元組:(stdoutdata, stderrdata)

subprocess還有另一種更簡單方法,效果一樣,它會返回stdout
>>> s = subprocess.check_output('ls -l', shell=True)
>>> s
'\xe6\x80\xbb\xe7\x94\xa8\xe9\x87\x8f 152\n-rw------- 1 limbo limbo   808  7\xe6\x9c\x88  6 17:46 0000-00-00-welcome-to-jekyll.markdown.erb\ndrwx------ 2 limbo limbo  4096  8\xe6\x9c\x88 15 18:43 arg\ndrwx------ 2 limbo limbo  4096  8\xe6\x9c\x88  7 17:37 argv\ndrwxrwxr-x 2 limbo limbo  4096  9\xe6\x9c\x88 10 15:27 c\ndrwxrwxr-x 3 limbo limbo  4096  9\xe6\x9c\x88 11 14:35 d3\ndrwxrwxr-x 3 limbo limbo  4096  9\xe6\x9n'

前者可以實現更多的互動,如stderr和stdin,但是在前面呼叫Popen的時候要實現定義Popen(stdin=subprocess.PIPE, stderr=subprocess)

給子程序輸入

import subprocess
child = subprocess.Popen(["cat"], stdin=subprocess.PIPE)
child.communicate("vamei")

()不為空,則寫入subprocess.PIPE,為空,則從subprocess.PIPE讀取

subprocess.PIPE介紹
#!/usr/bin/env python
import subprocess
child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
child2 = subprocess.Popen(["wc"], stdin=child1.stdout,stdout=subprocess.PIPE)
out = child2.communicate()
print out

實際上是這樣的過程
child1.stdout-->subprocess.PIPE

child2.stdin<--subprocess.PIPE

child2.stdout-->subprocess.PIPE
要注意的是,communicate()是Popen物件的一個方法,該方法會阻塞父程序,直到子程序完成。

subprocess.PIPE實際上為文字流提供一個快取區。直到communicate()方法從PIPE中讀取出PIPE中的文字.要注意的是,communicate()是Popen物件的一個方法,該方法會阻塞父程序,直到子程序完成。