天天看點

python中的subprocess

 python2.7 源碼中的注釋(由于能力有限,翻譯的不太準确):

這個子產品允許您開啟程序、連接配接輸入、輸出和錯誤的管道,并擷取他們的傳回代碼。這個子產品計劃替代一些舊代碼,如:

os.system、os.spawn*、os.Popen、popen2.* 、commands.*

關于subprocess子產品可以用來取代這些子產品和功能在下面可以找到

這個子產品定義了一個Popen的類:

  1. class Popen(args, bufsize=0, executable=None, 
  2.             stdin=None, stdout=None, stderr=None, 
  3.             preexec_fn=None, close_fds=False, shell=False, 
  4.             cwd=None, env=None, universal_newlines=False, 
  5.             startupinfo=None, creationflags=0): 

參數為:

args應該是一個字元串或序列的程式指令及參數。程式通常執行序列或字元串的第一項,但可以通過使用明确的參數進行設定。

在UNIX上,shell= True:如果參數是一個字元串,它指定了通過shell執行指令字元串。如果參數是一個序列,第一項指定指令字元串,其他的将被視為附加的shell指令的參數。

在Windows:Popen類通過使用CreateProcess()執行這個子程序來對字元串操作。如果參數是一個序列,它将用list2cmdline方法将其轉換成一個字元串。請注意,并不是所有的MS Windows應用程式解釋指令行用相同的方法:list2cmdline是專為應用程式與MS C使用相同的規則。 

bufsize,如果給定了,與内置行數open()的參數有相同意義:0意味着無緩沖的,1意味着線性緩沖,其他任何正值意味着使用的緩沖區(大約)大小。一個負bufsize意味着使用這個系統預設情況下,這通常意味着完全緩沖。預設值為bufsize是0(無緩沖的)。

stdin、stdout和stderr分别指定執行程式的标準輸入,标準輸出和标準錯誤。有效值是PIPE,現有的檔案描述符(正整數),現有檔案對象,None。PIPE建立一個新的子管道。None,沒有重定向;子管道将會繼承父管道的檔案句柄。此外,标準錯誤可以用STDOUT來定義,表明應用程式應該從STDOUT捕獲到相同的檔案句柄的标準錯誤資料。

如果preexec_fn設定為一個可調用對象,該對象将在子程序執行之前調用。

如果close_fds 為True,所有的檔案描述符除了0、1和2都會在子程序執行之前關閉。

如果shell是True,将通過shell執行指定的指令。

如果 cwd 不為None,子程序将在執行前切換到 cwd指定的目錄

如果 env 不為空,為新程序定義環境變量

如果 universal_newlines 為 True, 則檔案對象标準輸出、标準錯誤輸出以文本檔案形式打開, 但是在unix系統中會以\n結束,windows中以\r\n結束。 在python程式中都是看作為\n 注意: 這種功能僅僅支援用通用換行符建構的python(預設)。同時檔案對象标準輸出、标準輸入、标準錯誤的換行符屬性,不會被communicate()子產品所更新。

如果給定了startupinfo and creationflags參數, 将會轉交給底層CreateProcess() 函數,他們可以指定諸如主窗體的外觀、新程序的優先級之類的屬性(僅支援windows)

這個子產品也定義了一些簡短的函數:

call(*popenargs, **kwargs):

    運作帶參數的指令.  等待指令完成後傳回傳回碼屬性。

    這些參數相對于Popen構造函數是相同的。

    Example:

    retcode = call(["ls", "-l"])

check_call(*popenargs, **kwargs):

    運作帶參數的指令.  等待指令完成.如果退出碼是0則傳回,如果是其他則抛出      

    CalledProcessError錯誤,該CalledProcessError 對象就會有傳回傳回碼屬性

    check_call(["ls", "-l"])

check_output(*popenargs, **kwargs):

    運作帶參數的指令并且以位元組字元串來傳回。

    如果退出碼是非0則會抛出CalledProcessError。

    CalledProcessError的對象将有傳回代碼在returncode屬性和輸出在output屬性

    output = check_output(["ls", "-l", "/dev/null"])

異常處理:

==============

在新程式開始執行之前子程序抛出異常,之後父程序重新抛出異常。此外,異常對象會有一個額外稱為'child_traceback'的屬性,從子程序的角度上看,這是一個包含錯誤資訊的字元串。 

最常見的異常是OSError,比如:執行一個不存在的檔案,應用程式會抛出OSError異常

如果Popen被無效的參數調用就會抛出‘ValueError’

如果check_call() and check_output()在被調用過程中傳回一個非零的傳回碼則會抛出‘CalledProcessError’

安全

和其他popen函數不同,它不會隐式的執行/bin/sh,這意味着所有的字元,包括shell元字元,可以安全地傳遞給子程序。

Popen 對象

=============

Popen類的執行個體有以下方法

poll()

    檢查子程序是否終止,傳回returncode屬性

wait()

    等待子程序終止。傳回returncode屬性。

communicate(input=None)

    與程序互相作用: 發送資料到标準輸入。從标準輸出、标準錯誤讀取資料, 直到到達檔案尾。等待程序終止。可選的input參數應該是發送給子程序的字元串,或者如果沒有要發送給子程序的資料那就用None 

    communicate() 傳回一個元組 (stdout, stderr). 

    注意:讀取的資料是儲存在緩沖區中,是以,如果資料太大或沒有限制則不要使用這個方法

下面的屬性也是有效的:

===================== 

stdin

    如果stdin參數是PIPE,這個屬性是提供輸入到子程序一個檔案對象,否則為None

stdout

    如果stdout參數是PIPE , 這個屬性是提供輸出到子程序一個檔案對象,否則為None

stderr

     如果stderr參數是PIPE , 這個屬性是提供錯誤輸出到子程序一個檔案對象,否則為None

pid

    子程序的PID

returncode

    子程序的傳回碼。空值表示程序還沒有結束,一個負值‘-N’表示子程序被信号N所結束(僅unix支援)

用subprocess子產品取代舊函數:

====================================================

在本節中, "a ==> b" 意味着 b 可以替代 a.

注意: 如果沒有找到執行程式,所有在本節中的函數都有可能以靜默狀态失敗;這個子產品會抛出OSError異常

在以下的例子中, 我們假設subprocess 子產品是"from subprocess import *" 這樣導入的:

  1. 替代 /bin/sh shell 的引号部分 
  2. --------------------------------- 
  3. output=`mycmd myarg` 
  4. ==> 
  5. output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0] 
  6. 替代 shell 的管道
  7. ------------------------- 
  8. output=`dmesg | grep hda` 
  9. ==> 
  10. p1 = Popen(["dmesg"], stdout=PIPE) 
  11. p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) 
  12. output = p2.communicate()[0] 
  13. 替代 os.system() 
  14. --------------------- 
  15. sts = os.system("mycmd" + " myarg") 
  16. ==> 
  17. p = Popen("mycmd" + " myarg", shell=True) 
  18. pid, sts = os.waitpid(p.pid, 0) 
  19. 注意: 
  20. * 通過shell調用程式通常不是必須的 
  21. * 檢視returncode attribute要比exitstatus容易些. 
  22. 一個更現實的例子: 
  23. try: 
  24.     retcode = call("mycmd" + " myarg", shell=True) 
  25.     if retcode < 0: 
  26.         print >>sys.stderr, "Child was terminated by signal", -retcode 
  27.     else: 
  28.         print >>sys.stderr, "Child returned", retcode 
  29. except OSError, e: 
  30.     print >>sys.stderr, "Execution failed:", e 
  31. 替代 os.spawn* 
  32. ------------------- 
  33. P_NOWAIT example: 
  34. pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg") 
  35. ==> 
  36. pid = Popen(["/bin/mycmd", "myarg"]).pid 
  37. P_WAIT example: 
  38. retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg") 
  39. ==> 
  40. retcode = call(["/bin/mycmd", "myarg"]) 
  41. Vector example: 
  42. os.spawnvp(os.P_NOWAIT, path, args) 
  43. ==> 
  44. Popen([path] + args[1:]) 
  45. Environment example: 
  46. os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env) 
  47. ==> 
  48. Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"}) 
  49. 替代 os.popen* 
  50. ------------------- 
  51. pipe = os.popen("cmd", mode='r', bufsize) 
  52. ==> 
  53. pipe = Popen("cmd", shell=True, bufsize=bufsize, stdout=PIPE).stdout 
  54. pipe = os.popen("cmd", mode='w', bufsize) 
  55. ==> 
  56. pipe = Popen("cmd", shell=True, bufsize=bufsize, stdin=PIPE).stdin 
  57. (child_stdin, child_stdout) = os.popen2("cmd", mode, bufsize) 
  58. ==> 
  59. p = Popen("cmd", shell=True, bufsize=bufsize, 
  60.           stdin=PIPE, stdout=PIPE, close_fds=True) 
  61. (child_stdin, child_stdout) = (p.stdin, p.stdout) 
  62. (child_stdin, 
  63.  child_stdout, 
  64.  child_stderr) = os.popen3("cmd", mode, bufsize) 
  65. ==> 
  66. p = Popen("cmd", shell=True, bufsize=bufsize, 
  67.           stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) 
  68. (child_stdin, 
  69.  child_stdout, 
  70.  child_stderr) = (p.stdin, p.stdout, p.stderr) 
  71. (child_stdin, child_stdout_and_stderr) = os.popen4("cmd", mode, 
  72.                                                    bufsize) 
  73. ==> 
  74. p = Popen("cmd", shell=True, bufsize=bufsize, 
  75.           stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) 
  76. (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout) 
  77. 在 Unix系統中, os.popen2, os.popen3 與 os.popen4 同樣可以在沒有shell介入的情況下直接傳遞給程式
  78. 以序列形式執行指令行  
  79. 這種方法可以用下面的方法替換: 
  80. (child_stdin, child_stdout) = os.popen2(["/bin/ls", "-l"], mode, 
  81.                                         bufsize) 
  82. ==> 
  83. p = Popen(["/bin/ls", "-l"], bufsize=bufsize, stdin=PIPE, stdout=PIPE) 
  84. (child_stdin, child_stdout) = (p.stdin, p.stdout) 
  85. Return code handling translates as follows: 
  86. pipe = os.popen("cmd", 'w') 
  87. ... 
  88. rc = pipe.close() 
  89. if rc is not None and rc % 256: 
  90.     print "There were some errors" 
  91. ==> 
  92. process = Popen("cmd", 'w', shell=True, stdin=PIPE) 
  93. ... 
  94. process.stdin.close() 
  95. if process.wait() != 0: 
  96.     print "There were some errors" 
  97. 替代 popen2.* 
  98. ------------------ 
  99. (child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode) 
  100. ==> 
  101. p = Popen(["somestring"], shell=True, bufsize=bufsize 
  102.           stdin=PIPE, stdout=PIPE, close_fds=True) 
  103. (child_stdout, child_stdin) = (p.stdout, p.stdin) 
  104. 在 Unix系統中, popen2 也可以在沒有shell介入的情況下直接傳遞給程式以序列形式執行指令行.  
  105. 這種方法可以用下面的方法替換: 
  106. (child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, 
  107.                                             mode) 
  108. ==> 
  109. p = Popen(["mycmd", "myarg"], bufsize=bufsize, 
  110.           stdin=PIPE, stdout=PIPE, close_fds=True) 
  111. (child_stdout, child_stdin) = (p.stdout, p.stdin) 
  112. The popen2.Popen3 and popen2.Popen4 basically works as subprocess.Popen, 
  113. except that: 
  114. * subprocess.Popen raises an exception if the execution fails 
  115. * the capturestderr argument is replaced with the stderr argument. 
  116. * stdin=PIPE and stdout=PIPE must be specified. 
  117. * popen2 closes all filedescriptors by default, but you have to specify 
  118.   close_fds=True with subprocess.Popen.