Python之subprocess模塊

subprocess模塊容許你啓動一個新的進程,鏈接輸入/輸出/錯誤的管道, 
得到子進程的返回碼。這個模塊目標是代替一些老的模塊,好比os.system和os.spawn. 

python

0x01 常見subprocess方法

subprocess模塊中的經常使用函數

函數 描述
subprocess.run() Python 3.5中新增的函數。執行指定的命令,等待命令執行完成後返回一個包含執行結果的CompletedProcess類的實例。
subprocess.call() 執行指定的命令,返回命令執行狀態,其功能相似於os.system(cmd)。
subprocess.check_call() Python 2.5中新增的函數。 執行指定的命令,若是執行成功則返回狀態碼,不然拋出異常。其功能等價於subprocess.run(..., check=True)。
subprocess.check_output() Python 2.7中新增的的函數。執行指定的命令,若是執行狀態碼爲0則返回命令執行結果,不然拋出異常。
subprocess.getoutput(cmd) 接收字符串格式的命令,執行命令並返回執行結果,其功能相似於os.popen(cmd).read()和commands.getoutput(cmd)。
subprocess.getstatusoutput(cmd) 執行cmd命令,返回一個元組(命令執行狀態, 命令執行結果輸出),其功能相似於commands.getstatusoutput()。

subprocess.run(args*stdin=Noneinput=Nonestdout=Nonestderr=Noneshell=Falsetimeout=Nonecheck=False)

args    該參數用於啓動進程。這多是一個列表或一個字符串。
returncode   該參數表示子進程的退出狀態。
一般狀況下,0做爲退出狀態代表它成功運行。
負值-N代表子進程被信號N終止(僅POSIX)。
stdout  該參數表示標準輸出

此調用方式返回CompletedProcess實例,和直接Popen 差很少,實現是同樣的,實際也是調用Popen,與Popen構造函數大體相同,例如:shell

>>> subprocess.run(["ls", "-l"]) # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)api

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1數組

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')緩存


subprocess.call()

執行由參數提供的命令.
咱們能夠用數組做爲參數運行命令,也能夠用字符串做爲參數運行命令(經過設置參數shell=True)
注意,參數shell默認爲Falsesession

subprocess.call(['ipconfig','/all'])

subprocess.call('ipconfig /all',shell=True)

 subprocess.getoutput(cmd)

cmd能夠直接執行shell命令,而不須要cmd命令以列表輸入---subprocess.getoutput("cat /proc/meminfo")
返回值包含cmd的執行結果,能夠直接賦值給某個變量
功能和getstatusoutput相似
a=subprocess.getoutput('ipconfig /all')
print(a)

subprocess.getstatusoutput(cmd)

cmd能夠直接執行shell命令,而不須要cmd命令以列表輸入----subprocess.getstatusoutput("cat /proc/meminfo")函數

返回值包含cmd的執行狀態和執行結果,能夠直接賦值給某個變量,返回的是一個元組spa

a=subprocess.getstatusoutput('ipconfig /all')
print(a)

 

subprocess.check_call()

check_call基本和call功能同樣,只是增長了返回狀態碼校驗,若是執行狀態碼是0,則返回0,不然拋出異常rest

subprocess.check_call(['ipconfig',  '/all'])

subprocess.check_output()

執行命令,若是狀態碼是0,則返回執行結果,不然拋出異常--
a=subprocess.check_output(['ipconfig',  '/all'])
print(a)


0x0二、subprocess.Popen()類

該類用於在一個新的進程中執行一個子程序。前面咱們提到過,上面介紹的這些函數都是基於subprocess.Popen類實現的,經過使用這些被封裝後的高級函數能夠很方面的完成一些常見的需求。因爲subprocess模塊底層的進程建立和管理是由Popen類來處理的,所以,當咱們沒法經過上面哪些高級函數來實現一些不太常見的功能時就能夠經過subprocess.Popen類提供的靈活的api來完成。code

1.subprocess.Popen的構造函數

def __init__(self, args, bufsize=-1, executable=None,
                 stdin=None, stdout=None, stderr=None,
                 preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
                 shell=False, cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0,
                 restore_signals=True, start_new_session=False,
                 pass_fds=(), *, encoding=None, errors=None)
參數說明:
  • 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
 
相關文章
相關標籤/搜索