day5-subprocess模塊

1、概述

實際應用中,有些時候咱們不得不跟操做系統進行指令級別的交互,如Linux中的shell。Python中早期經過os模塊和commands模塊來實現操做系統級別的交互,但從2.4版本開始,官方建議使用subprocess模塊。所以對於os和commands模塊只會簡單講解,重點會放在subprocess模塊和Popen類上。html

對於指令的執行,咱們通常關注如下兩點:python

  1. 命令執行的狀態碼--表示命令執行是否成功
  2. 命令執行的輸出結果--命令執行成功後的輸出

2、os與commands模塊

Python中提供瞭如下幾個函數來幫助咱們完成命令行指令的執行:linux

image

說明:redis

  1. os.popen(command)函數獲得的是一個文件對象,所以除了read()方法外還支持write()等方法,具體要根據command來定;
  2. commands模塊只存在於Python 2.7中,且不支持windows平臺,所以commands模塊不多被使用。另外,commands模塊實際上也是經過對os.popen()的封裝來完成的。

以上內容轉載自http://www.cnblogs.com/yyds/p/7288916.html,下面是簡單的程序示例:shell

  • os.system()
     1 >>> import os
     2 >>> os.system('pwd')
     3 /root   #命令執行結果
     4 0       #命令執行狀態
     5 >>> os.system('pwd1')
     6 sh: pwd1: command not found
     7 32512
     8 >>> res=os.system('wget')
     9 wget: missing URL
     10 Usage: wget [OPTION]... [URL]...
     11 
     12 Try ‘wget --help’ for more options.
     13 >>> res=os.system('redis')
     14 sh: redis: command not found   #命令執行結果
     15 >>> res
     16 32512   #命令執行狀態
    上述程序代表,os.system一次性返回命令執行結果和執行狀態返回碼,若是用變量存儲,則須要單獨獲取狀態碼。
  • os.popen()
    建立一個文件對象,須要經過read()方法獲取,而且只會返回命令執行結果,沒有狀態碼
     1 >>> import os
     2 >>> os.popen('uptime')
     3 <open file 'uptime', mode 'r' at 0x7ff37451cc00>
     4 >>> print(os.popen('uptime').read())
     5  07:21:57 up 33 days,  2:00,  1 user,  load average: 0.00, 0.00, 0.00
  • commands.getstatusoutput()
     1 >>> import commands
     2 >>> commands.getstatusoutput('who')
     3 (0, 'root     pts/0        2018-03-05 07:15 (172.17.35.6)')
     4 >>> commands.getstatusoutput('uptime')
     5 (0, ' 07:24:34 up 33 days,  2:02,  1 user,  load average: 0.00, 0.00, 0.00')
    須要注意的是commands模塊僅支持linux平臺,且在python 3.5版本後再也不支持

3、subprocess模塊的經常使用函數

subprocess模塊是關鍵建議使用的模塊,顧名思義是創建一個子進程,用來運行與系統交互的指令。Subporcess模塊經常使用的函數有如下幾類:
imagewindows

說明:api

  1. 在Python 3.5以後的版本中,官方文檔中提倡經過subprocess.run()函數替代其餘函數來使用subproccess模塊的功能;
  2. 在Python 3.5以前的版本中,咱們能夠經過subprocess.call(),subprocess.getoutput()等上面列出的其餘函數來使用subprocess模塊的功能;
  3. subprocess.run()、subprocess.call()、subprocess.check_call()和subprocess.check_output()都是經過對subprocess.Popen的封裝來實現的高級函數,所以若是咱們須要更復雜功能時,能夠經過subprocess.Popen來完成。
  4. subprocess.getoutput()和subprocess.getstatusoutput()函數是來自Python 2.x的commands模塊的兩個遺留函數。它們隱式的調用系統shell,而且不保證其餘函數所具備的安全性和異常處理的一致性。另外,它們從Python 3.3.4開始才支持Windows平臺。


上述內容轉載自http://www.cnblogs.com/yyds/p/7288916.html數組

下面詳解講解函數的具體用法。緩存

3.1 subprocess.run()

語法:subprocess.run(args, *, stdin=None, stdout=None, stderr=None, shell=False)
使用說明:這是python 3.5版本才新增出現的函數,用於執行指定的命令,等待命令執行完成後返回一個包含執行結果的CompletedProcess類的實例。
這裏重點講述下shell=False這個參數:
默認狀況下這個參數爲False,不調用shell自己支持的一些特性(如管道、文件名通配符、環境變量擴展功能)必須以列表形式傳遞須要執行的命令,第一個元素做爲命令,後續的元素做爲命令參數;而shell=True參數會讓subprocess.call接受字符串類型的變量做爲命令,並調用shell去執行這個字符串(可使用shell的特性了,如管道、文件名通配符、環境變量擴展功能),若是命令使用了shell的分隔符,那麼還能夠一次性執行多條命令,使用起來很方便。
問題來了,既然shell=True使用更方便,爲何默認值是Flase呢?這是由於萬一對傳入的命令檢查不夠仔細,執行了危險的命令好比 rm -rf / 這種那後果會很是嚴重,而使用shell=False就能夠避免這種風險,所以是一種安全機制。
仍是上程序把(程序在linux下運行效果更直觀):安全

 1 >>> import subprocess
 2 >>> subprocess.run(['ls', '-l'])  #列表形式傳遞命令
 3 total 28
 4 -rw-------. 1 root root 1096 Sep 24  2015 anaconda-ks.cfg
 5 -rw-r--r--  1 root root  238 Jan 11 13:12 history_command
 6 -rw-r--r--. 1 root root 8835 Sep 24  2015 install.log
 7 -rw-r--r--. 1 root root 3384 Sep 24  2015 install.log.syslog
 8 drwxr-xr-x  3 root root 4096 Mar  6 04:55 software
 9 CompletedProcess(args=['ls', '-l'], returncode=0)#返回了狀態碼
 10 >>> subprocess.run('ls -l', shell=True)
 11 total 28
 12 -rw-------. 1 root root 1096 Sep 24  2015 anaconda-ks.cfg
 13 -rw-r--r--  1 root root  238 Jan 11 13:12 history_command
 14 -rw-r--r--. 1 root root 8835 Sep 24  2015 install.log
 15 -rw-r--r--. 1 root root 3384 Sep 24  2015 install.log.syslog
 16 drwxr-xr-x  3 root root 4096 Mar  6 04:55 software
 17 CompletedProcess(args='ls -l', returncode=0) #單字符串形式傳遞命令
 18 >>> subprocess.run('ls|wc -l', shell=True)
 19 5
 20 CompletedProcess(args='ls|wc -l', returncode=0)
 21 >>> subprocess.run('ls|wc -l')
 22 Traceback (most recent call last):
 23   File "<stdin>", line 1, in <module>
 24   File "/usr/local/python_3.6.2/lib/python3.6/subprocess.py", line 403, in run
 25     with Popen(*popenargs, **kwargs) as process:
 26   File "/usr/local/python_3.6.2/lib/python3.6/subprocess.py", line 707, in __init__
 27     restore_signals, start_new_session)
 28   File "/usr/local/python_3.6.2/lib/python3.6/subprocess.py", line 1333, in _execute_child
 29     raise child_exception_type(errno_num, err_msg)
 30 FileNotFoundError: [Errno 2] No such file or directory: 'ls|wc -l'

注意:

若是必須使用shell的特性而沒有設置shell的參數爲Ture,程序會直接報錯沒有該文件或目錄。

3.2 subprocess.call()

語法:subprocess.run(args, *, stdin=None, stdout=None, stderr=None, shell=False)
使用說明:執行指定的命令,返回執行狀態返回碼,其功能相似於os.system(cmd)。在使用這個函數時,不要使用 stdout=PIPE 或 stderr=PIPE 參數,否則會致使子進程輸出的死鎖。若是要使用管道,能夠在 communicate()方法中使用Popen(網上看到的論述,須要後續實踐)

 1 >>> import subprocess
 2 >>> subprocess.call('ls|wc -l', shell=True)  #管道符,必須調用shell才能支持
 3 37  #命令執行結果
 4 0   #命令執行狀態返回碼

3.3 subprocess.check_call()

語法:subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
使用說明:運行由args指定的命令,直到命令執行完成。若是返回碼爲零,則返回。不然,拋出 CalledProcessError異常。CalledProcessError對象包含有返回碼的屬性值。

 1 >>> import subprocess
 2 >>> subprocess.check_call('ls -l', shell=True)
 3 total 28
 4 -rw-------. 1 root root 1096 Sep 24  2015 anaconda-ks.cfg
 5 -rw-r--r--  1 root root  238 Jan 11 13:12 history_command
 6 -rw-r--r--. 1 root root 8835 Sep 24  2015 install.log
 7 -rw-r--r--. 1 root root 3384 Sep 24  2015 install.log.syslog
 8 drwxr-xr-x  3 root root 4096 Mar  6 04:55 software
 9 0返回碼
 10 >>> subprocess.check_call('ls1', shell=True) #執行出錯
 11 /bin/sh: ls1: command not found
 12 Traceback (most recent call last):
 13   File "<stdin>", line 1, in <module>
 14   File "/usr/local/python_3.6.2/lib/python3.6/subprocess.py", line 291, in check_call
 15     raise CalledProcessError(retcode, cmd)
 16 subprocess.CalledProcessError: Command 'ls1' returned non-zero exit status 127.
注意:細心的同窗可能會發現程序執行後返回的不僅是狀態碼,還有傳遞的指令執行的結果,注意命令執行執行的結果是subprocess建立的子進程執行命令後返回的輸出,上述幾個函數都是這樣。何以見得?
 1 >>> import subprocess
 2 >>> res=subprocess.check_call('ls', shell=True)
 3 anaconda-ks.cfg  history_command  install.log  install.log.syslog  software
 4 >>> res
 5 0

3.4 subprocess.check_output()

語法:subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None)
使用說明:
Python 2.7中新增的的函數。執行指定的命令,若是執行狀態碼爲0則返回命令執行結果,不然拋出CalledProcessError異常。
universal_newlines參數說明: 該參數影響的是輸入與輸出的數據格式,好比它的值默認爲False,此時stdout和stderr的輸出是字節序列;當該參數的值設置爲True時,stdout和stderr的輸出是字符串。

 1 >>> import subprocess
 2 >>> subprocess.check_output('ls', shell=True)     #默認返回的結果是字節序列
 3 b'anaconda-ks.cfg\nhistory_command\ninstall.log\ninstall.log.syslog\nsoftware\n'
 4 >>> subprocess.check_output('ls', shell=True, universal_newlines=True) #輸出字符串形式
 5 'anaconda-ks.cfg\nhistory_command\ninstall.log\ninstall.log.syslog\nsoftware\n'
 6 >>> subprocess.check_output('ls1', shell=True, universal_newlines=True) #執行失敗
 7 /bin/sh: ls1: command not found
 8 Traceback (most recent call last):
 9   File "<stdin>", line 1, in <module>
 10   File "/usr/local/python_3.6.2/lib/python3.6/subprocess.py", line 336, in check_output
 11     **kwargs).stdout
 12   File "/usr/local/python_3.6.2/lib/python3.6/subprocess.py", line 418, in run
 13     output=stdout, stderr=stderr)
 14 subprocess.CalledProcessError: Command 'ls1' returned non-zero exit status 127.

注意:

1. 不要在這個函數中使用 stdout=PIPE 或 stderr=PIPE, 不然會形成子進程死鎖。若是須要使用管道,能夠在 communicate()方法中使用Popen.

2. 若是要捕捉結果中的標準錯誤,可以使用 stderr=subprocess.STDOUT參數,實際測試也只是輸出了狀態碼,並無給出具體的錯誤緣由信息,待後續驗證。

3.5 subprocess.getoutput()

語法:subprocess.getoutput(cmd)
使用說明:接收字符串格式的命令,執行命令並返回執行結果,其功能相似於os.popen(cmd).read()和commands.getoutput(cmd)。

 1 >>> import subprocess
 2 >>> subprocess.getoutput('ls', shell=True)
 3 Traceback (most recent call last):
 4   File "<stdin>", line 1, in <module>
 5 TypeError: getoutput() got an unexpected keyword argument 'shell'  #再也不接受其餘參數
 6 >>>
 7 >>> subprocess.getoutput('ls')     #純字符串形式輸出結果
 8 'anaconda-ks.cfg\nhistory_command\ninstall.log\ninstall.log.syslog\nsoftware'
 9 >>> subprocess.getoutput('ls1')
 10 '/bin/sh: ls1: command not found'

3.6 subprocess.getstatusoutput()

語法:subprocess.getstatusoutput(cmd)
使用說明:執行cmd命令,返回一個元組(命令執行狀態, 命令執行結果輸出),其功能相似於commands.getstatusoutput()。

 1 >>> import subprocess
 2 >>> subprocess.getstatusoutput('ls')
 3 (0, 'anaconda-ks.cfg\nhistory_command\ninstall.log\ninstall.log.syslog\nsoftware')
 4 >>> subprocess.getstatusoutput('ls1')
 5 (127, '/bin/sh: ls1: command not found')
 6 >>>

4、subprocess.Popen()

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

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

參數說明:

args: 要執行的shell命令,能夠是字符串,也能夠是命令各個參數組成的序列。當該參數的值是一個字符串時,該命令的解釋過程是與平臺相關的,所以一般建議將args參數做爲一個序列傳遞。
bufsize: 指定緩存策略,0表示不緩衝,1表示行緩衝,其餘大於1的數字表示緩衝區大小,負數表示使用系統默認緩衝策略。
stdin, stdout, stderr: 分別表示程序標準輸入、輸出、錯誤句柄。 它們的值能夠是PIPE, 一個存在的文件描述符(正整數),一個存在的文件對象或 None.
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()函數,用於設置子進程的一些屬性,如主窗口的外觀,進程優先級等

4.1 Popen類的經常使用方法

Open類的經常使用方法大概可分爲兩類,一類是與子進程進行交互的方法,如stdin,stdout,stderr,communicate,kill,terminate,send_signal,另一類是獲取子進程的狀態信息,如pid,poll,下面逐一展開它們的用法:

  1. stdin
    stdin實現向子進程的輸入。
     1 >>> import subprocess
     2 >>> p1=subprocess.Popen(['python'], stdin=subprocess.PIPE, stdout=subprocess.PIP
     3 E, stderr=subprocess.PIPE)
     4 >>>
     5 >>>
     6 >>> p1.stdin.write("print('Hello World!')")
     7 Traceback (most recent call last):
     8   File "<stdin>", line 1, in <module>
     9 TypeError: a bytes-like object is required, not 'str'
     10 >>> p1=subprocess.Popen(['python'], stdin=subprocess.PIPE, stdout=subprocess.PIP
     11 E, stderr=subprocess.PIPE, universal_newlines=True)
     12 >>>
     13 >>> p1.stdin.write("print('Hello World!')")
     14 21
     15 >>> out,err=p1.communicate()
     16 >>> p1.stdin.close()
     17 >>> print(out)
     18 Hello World!
     19
    注意上述示例程序中的universal_newlines=True參數,不使用該參數輸入時會提示輸入的對象必須是二進制類型的,使用後才能直接輸入文本流。
    communicate在下文單獨講述。
  2. stdout
    stdout捕獲子進程的輸出
     1 import subprocess
     2 
     3 p1 = subprocess.Popen(['dir'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     4 print(p1.stdout.read())
     5 
     6 輸出:
     7 驅動器 D 中的卷是 本地磁盤
     8  卷的序列號是 6651-23F0
     9 
     10  D:\python\S13\Day5\test 的目錄
     11 
     12 2018/03/10  08:07    <DIR>          .
     13 2018/03/10  08:07    <DIR>          ..
     14 2017/12/26  07:43                 8 1.txt
     15 2017/12/26  06:32               374 2.py
     16 ...
    注意:在windows平臺下運行相似程序時,因爲不少命令都是cmd.exe支持的,所以須要加上shell=True參數,不然會提示找不到文件。
  3. stderr
    stderr用於捕獲子進程的錯誤輸出,前提是程序自己沒有語法錯誤,能正常進入到子程序執行環節
     1 import subprocess
     2 
     3 p1 = subprocess.Popen(['dir 1'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     4 print(p1.stderr.read())
     5 
     6 輸出:
     7 '"dir 1"' 不是內部或外部命令,也不是可運行的程序
     8 或批處理文件。
  4. commucate()與死鎖問題
    誠然,上面講述的講述的stdin,stdout,stderr也能完成與子進程的一些必要交互(輸入,捕獲輸出好,捕獲錯誤),他們都經過PIPE管道來進行處理,大體流程以下:
    image
    因爲PIPE本質上是問文本流提供一個緩衝區,其容量是有限的,所以比較安全的作法是及時清理管道的內容,以免可能的死鎖問題。

    死鎖問題:
    若是你使用了管道,而又不去處理管道的輸出,那麼當心點,若是子進程輸出數據過多,死鎖就會發生了,好比下面的用法:
    p=subprocess.Popen("longprint", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p.wait()
    longprint是一個假想的有大量輸出的進程,那麼在個人xp, Python2.5的環境下,當輸出達到4096時,死鎖就發生了。固然,若是咱們用p.stdout.readline或者p.communicate去清理輸出,那麼不管輸出多少,死鎖都是不會發生的。或者咱們不使用管道,好比不作重定向,或者重定向到文件,也都是能夠避免死鎖的。
    官方文檔裏推薦使用 Popen.communicate()。這個方法會把輸出放在內存,而不是管道里,因此這時候上限就和內存大小有關了,通常不會有問題。並且若是要得到程序返回值,能夠在調用 Popen.communicate() 以後取 Popen.returncode 的值。

    p.communicate()會當即阻塞父進程,直到子進程執行完畢,在不超過內存狀況下還能避免wait()阻塞父進程可能帶來的死鎖問題,所以通常狀況下推薦使用(子進程輸出不超過內存大小)。
    它自己附帶input和timeout參數,它的輸出是一個包含標準輸出和錯誤輸出的元組(stdout,stderr),咱們通常使用out,err=p.communicate()來分別處理stdout和stderr。
     1 import subprocess
     2 
     3 p1 = subprocess.Popen(['python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
     4 p1.communicate(input="print('Hello world!')")
     5 out,err=p1.communicate()
     6 print(p1.communicate())
     7 print(out)
     8 
     9 輸出:
     10 ('Hello world!\n', '')
     11 Hello world!
     12
    捕獲錯誤輸出:
     1 >>> import subprocess
     2 >>> p1 = subprocess.Popen(['ls','007'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
     3 >>> out,err=p1.communicate()
     4 >>> print(err)
     5 ls: cannot access 007: No such file or directory

    若是子進程輸出過多,仍是要考慮經過文件來接收輸出,方法是把stdout指向一個open好的具有寫權限的文件對象(還記得stdin,stdout,stderr就是相應的句柄嗎)便可:
     1 >>> import subprocess
     2 >>> file = open('file.log', encoding='utf-8', mode='a')
     3 >>> p1 = subprocess.Popen('ping -c 10 baidu.com', stdin=subprocess.PIPE, stdout=file, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     4 >>> print(p1.communicate())
     5 (None, '')
     6 >>> quit()
     7 [root@test211 ~]# ls -ltr
     8 total 32
     9 -rw-r--r--. 1 root root 3384 Sep 24  2015 install.log.syslog
     10 -rw-r--r--. 1 root root 8835 Sep 24  2015 install.log
     11 -rw-------. 1 root root 1096 Sep 24  2015 anaconda-ks.cfg
     12 -rw-r--r--  1 root root  238 Jan 11 13:12 history_command
     13 drwxr-xr-x  3 root root 4096 Mar  6 04:55 software
     14 -rw-r--r--  1 root root  818 Mar 11 07:10 file.log
     15 [root@test211 ~]# cat file.log
     16 PING baidu.com (111.13.101.208) 56(84) bytes of data.
     17 64 bytes from 111.13.101.208: icmp_seq=1 ttl=52 time=43.7 ms
     18 64 bytes from 111.13.101.208: icmp_seq=2 ttl=52 time=42.4 ms
     19 64 bytes from 111.13.101.208: icmp_seq=3 ttl=52 time=43.1 ms
     20 64 bytes from 111.13.101.208: icmp_seq=4 ttl=52 time=43.6 ms
     21 64 bytes from 111.13.101.208: icmp_seq=5 ttl=52 time=43.5 ms
     22 64 bytes from 111.13.101.208: icmp_seq=6 ttl=52 time=43.7 ms
     23 64 bytes from 111.13.101.208: icmp_seq=7 ttl=52 time=43.4 ms
     24 64 bytes from 111.13.101.208: icmp_seq=8 ttl=52 time=42.4 ms
     25 64 bytes from 111.13.101.208: icmp_seq=9 ttl=52 time=43.6 ms
     26 64 bytes from 111.13.101.208: icmp_seq=10 ttl=52 time=43.6 ms
     27 
     28 --- baidu.com ping statistics ---
     29 10 packets transmitted, 10 received, 0% packet loss, time 9058ms
     30 rtt min/avg/max/mdev = 42.437/43.349/43.760/0.479 ms
    這方面的示例還比較粗淺,實際場景的用法,還有待後續實踐深刻。
  5. poll()
    定時檢查子進程是否已結束,結束則返回0,反之返回None
     1 >>> import subprocess
     2 >>> p1 = subprocess.Popen(["ping -c 10 baidu.com"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     3 >>> print(p1.poll())
     4 None #子進程未結束
     5 >>> print(p1.poll())
     6 0 #子進程已結束
  6. wait()
    阻塞父進程,等待子進程結束,並返回子進程執行狀態碼
     1 >>> import subprocess
     2 >>> p1 = subprocess.Popen(["ping -c 10 baidu.com"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     3 >>> p1.wait()
     4 0
     5 >>> import subprocess
     6 >>> p2 = subprocess.Popen(["sleep 15;ls 007"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     7 >>> p2.wait()
     8 2
     9 >>> p3 = subprocess.Popen(["sleep 15;pwd1"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     10 >>> p3.wait()
     11 127
    從上述程序可看出,返回的子進程狀態碼,非0表明執行失敗。
  7. pid()
    返回父進程的pid,即發起Popen的進程,注意並不是發起的子進程
     1 >>> import subprocess
     2 >>> p1 = subprocess.Popen(["ping -c 5 baidu.com"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     3 >>> print(p1.pid)
     4 4219
     5 
     6 查看pid的進程
     7 [root@test211 ~]# ps -ef|grep 4219
     8 root      4219  4218  0 21:37 pts/0    00:00:00 [ping] <defunct>
     9 root      4223  4150  0 21:38 pts/1    00:00:00 grep --color 4219
    這裏須要注意的是,子進程的命令執行完畢,父進程不會本身結束,感興趣的同窗能夠持續觀察ps -ef的輸出
  8. kill()
    殺死子進程,注意發起Popen的父進程不受影響。對比測試:
    正常執行子進程的命令:
     1 import subprocess
     2 p1 = subprocess.Popen('ping  -n 5 baidu.com', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     3 out,error=p1.communicate()
     4 print(p1.pid)
     5 print(out)
     6 
     7 輸出:
     8 9060
     9 
     10 正在 Ping baidu.com [111.13.101.208] 具備 32 字節的數據:
     11 來自 111.13.101.208 的回覆: 字節=32 時間=33ms TTL=55
     12 來自 111.13.101.208 的回覆: 字節=32 時間=33ms TTL=55
     13 來自 111.13.101.208 的回覆: 字節=32 時間=34ms TTL=55
     14 來自 111.13.101.208 的回覆: 字節=32 時間=69ms TTL=55
     15 來自 111.13.101.208 的回覆: 字節=32 時間=33ms TTL=55
     16 
     17 111.13.101.208 的 Ping 統計信息:
     18     數據包: 已發送 = 5,已接收 = 5,丟失 = 0 (0% 丟失),
     19 往返行程的估計時間(以毫秒爲單位):
     20     最短 = 33ms,最長 = 69ms,平均 = 40ms
    調用kill()方法後:
     1 import subprocess
     2 p1 = subprocess.Popen('ping  -n 5 baidu.com', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     3 p1.kill()
     4 out,error=p1.communicate()
     5 print(p1.pid)
     6 print(out)
     7 
     8 輸出:(只能獲取到pid,子進程沒有任何輸出了)
     9 9144
  9. terminate()
    終止子進程 p ,等於向子進程發送 SIGTERM 信號。
     1 import subprocess
     2 p1 = subprocess.Popen('ping  -n 5 baidu.com', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     3 p1.terminate() #終止子進程
     4 out,error=p1.communicate()
     5 print(p1.pid)
     6 print(out)
     7 
     8 輸出:(沒有子進程的任何輸出了)
     9 7448
  10. send_signal()
    向子進程發送信號,Linux下有用。之後用到再說把。
  11. returncode
    返回子進程的執行狀態碼,至關於Linux下的$?,便於判斷子進程命令是否執行成功。0表示子進程命令執行ok,非0表示執行有誤。
     1 >>> import subprocess
     2 >>> p1 = subprocess.Popen('ping  -c 5 baidu.com', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     3 >>> print(p1.returncode)
     4 None
     5 >>> out,error=p1.communicate()
     6 >>> print(p1.returncode)
     7 0
     8 >>> p2 = subprocess.Popen('ping1  -c 5 baidu.com', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
     9 >>> out,error=p2.communicate()
     10 >>> print(p2.returncode)
     11 127
     12 >>>

實際應用中,可能還存在處理異步subprocess的需求,到時再深刻學習了。

相關文章
相關標籤/搜索