1. 程式人生 > >subprocess.Popen模組

subprocess.Popen模組

該類用於在一個新的程序中執行一個子程式。subprocess模組底層的程序建立和管理是由Popen類來處理的。

1.subprocess.Popen的建構函式

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, 
    preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False,
    startup_info=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=())

引數說明:
args: 要執行的shell命令,可以是字串,也可以是命令各個引數組成的序列。當該引數的值是一個字串時,該命令的解釋過程是與平臺相關的,因此通常建議將args引數作為一個序列傳遞。
bufsize: 指定快取策略,0表示不緩衝,1表示行緩衝,其他大於1的數字表示緩衝區大小,負數表示使用系統預設緩衝策略。
stdin, stdout, stderr: 分別表示程式標準輸入、輸出、錯誤控制代碼。
preexec_fn: 用於指定一個將在子程序執行之前被呼叫的可執行物件,只在Unix平臺下有效。
close_fds: 如果該引數的值為True,則除了0,1和2之外的所有檔案描述符都將會在子程序執行之前被關閉。
shell: 該引數用於標識是否使用shell作為要執行的程式,如果shell值為True,則建議將args引數作為一個字串傳遞而不要作為一個序列傳遞。
cwd: 如果該引數值不是None,則該函式將會在執行這個子程序之前改變當前工作目錄。
env: 用於指定子程序的環境變數,如果env=None,那麼子程序的環境變數將從父程序中繼承。如果env!=None,它的值必須是一個對映物件。
universal_newlines: 如果該引數值為True,則該檔案物件的stdin,stdout和stderr將會作為文字流被開啟,否則他們將會被作為二進位制流被開啟。
startupinfo和creationflags: 這兩個引數只在Windows下有效,它們將被傳遞給底層的CreateProcess()函式,用於設定子程序的一些屬性,如主視窗的外觀,程序優先順序等。

2. subprocess.Popen類的例項可呼叫的方法

方法 描述
Popen.poll() 用於檢查子程序(命令)是否已經執行結束,沒結束返回None,結束後返回狀態碼。
Popen.wait(timeout=None) 等待子程序結束,並返回狀態碼;如果在timeout指定的秒數之後程序還沒有結束,將會丟擲一個TimeoutExpired異常。
Popen.communicate(input=None, timeout=None)  該方法可用來與程序進行互動,比如傳送資料到stdin,從stdout和stderr讀取資料,直到到達檔案末尾。
Popen.send_signal(signal)  傳送指定的訊號給這個子程序。
Popen.terminate()  停止該子程序。
Popen.kill()  殺死該子程序。

             

關於communicate()方法的說明:

該方法中的可選引數 input 應該是將被髮送給子程序的資料,如果沒有資料傳送給子程序,該引數應該是None。input引數的資料型別必須是位元組串,如果universal_newlines引數值為True,則input引數的資料型別必須是字串。

該方法返回一個元組(stdout_data, stderr_data),這些資料將會是位元組串或字串(如果universal_newlines的值為True)。
如果在timeout指定的秒數後該程序還沒有結束,將會丟擲一個TimeoutExpired異常。捕獲這個異常,然後重新嘗試通訊不會丟失任何輸出的資料。但是超時之後子程序並沒有被殺死,為了合理的清除相應的內容,一個好的應用應該手動殺死這個子程序來結束通訊。

需要注意的是,這裡讀取的資料是緩衝在記憶體中的,所以,如果資料大小非常大或者是無限的,就不應該使用這個方法。

3. subprocess.Popen使用例項

例項1:

>>> import subprocess
>>>
>>> p = subprocess.Popen('df -Th', stdout=subprocess.PIPE, shell=True)
>>> print(p.stdout.read())
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/vda1      ext4       40G   12G   26G  31% /
devtmpfs       devtmpfs  3.9G     0  3.9G   0% /dev
tmpfs          tmpfs     3.9G     0  3.9G   0% /dev/shm
tmpfs          tmpfs     3.9G  386M  3.5G  10% /run
tmpfs          tmpfs     3.9G     0  3.9G   0% /sys/fs/cgroup
tmpfs          tmpfs     783M     0  783M   0% /run/user/0
tmpfs          tmpfs     783M     0  783M   0% /run/user/1000

 

例項2:

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> obj.stdin.write('print(1) \n')
>>> obj.stdin.write('print(2) \n')
>>> obj.stdin.write('print(3) \n')
>>> out,err = obj.communicate()
>>> print(out)
1
2
3

>>> print(err)

 

例項3:

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out,err = obj.communicate(input='print(1) \n')
>>> print(out)
1

>>> print(err)

 

例項4:
實現類似df -Th | grep data命令的功能,實際上就是實現shell中管道的共功能。

>>> p1 = subprocess.Popen(['df', '-Th'], stdout=subprocess.PIPE)
>>> p2 = subprocess.Popen(['grep', 'data'], stdin=p1.stdout, stdout=subprocess.PIPE)
>>> out,err = p2.communicate()
>>> print(out)
/dev/vdb1 ext4 493G 4.8G 463G 2% /data
/dev/vdd1 ext4 1008G 420G 537G 44% /data1
/dev/vde1 ext4 985G 503G 432G 54% /data2

>>> print(err)
None

 

例項5:

import subprocess

'''
sh-3.2# ls /Users/egon/Desktop |grep txt$
mysql.txt
tt.txt
事物.txt
'''

res1=subprocess.Popen('ls /Users/jieli/Desktop |grep txt$',shell=True,stdout=subprocess.PIPE)
print(res1.stdout.read().decode('utf-8')) #等同於上面,也可以一個數據流可以和另外一個數據流互動,可以通過爬蟲得到結果然後交給grep res1=subprocess.Popen('ls /Users/jieli/Desktop',shell=True,stdout=subprocess.PIPE) res=subprocess.Popen('grep txt$',shell=True,stdin=res1.stdout,stdout=subprocess.PIPE)
print(res.stdout.read().decode('utf-8')) #windows下: # dir | findstr 'test*' # dir | findstr 'txt$' import subprocess res1=subprocess.Popen(r'dir C:\Users\Administrator\PycharmProjects\test\函式備課',shell=True,stdout=subprocess.PIPE) res=subprocess.Popen('findstr test*',shell=True,stdin=res1.stdout,stdout=subprocess.PIPE)
print(res.stdout.read().decode('gbk')) #subprocess使用當前系統預設編碼,得到結果為bytes型別,在windows下需要用gbk解碼