Popen 具有更大的靈活性

subprocess.call 相比,使用 subprocess.Popen 可以對啟動的程序進行更細粒度的控制。

啟動子流程

process = subprocess.Popen([r'C:\path\to\app.exe', 'arg1', '--flag', 'arg'])

Popen 的簽名與 call 函式非常相似; 但是,Popen 將立即返回,而不是像 call 那樣等待子程序完成。

等待子程序完成

process = subprocess.Popen([r'C:\path\to\app.exe', 'arg1', '--flag', 'arg'])
process.wait()

從子程序讀取輸出

process = subprocess.Popen([r'C:\path\to\app.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

# This will block until process completes
stdout, stderr = process.communicate()
print stdout
print stderr

對正在執行的子程序的互動式訪問

即使子程序尚未完成,你也可以在 stdinstdout 上進行讀寫。當在另一個程式中自動執行功能時,這可能很有用。

寫入子程序

process = subprocess.Popen([r'C:\path\to\app.exe'], stdout = subprocess.PIPE, stdin = subprocess.PIPE)

process.stdin.write('line of input\n') # Write input

line  = process.stdout.readline() # Read a line from stdout

# Do logic on line read.

但是,如果你只需要一組輸入和輸出,而不是動態互動,則應使用 communicate() 而不是直接訪問 stdinstdout

從子程序讀取流

如果你想逐行檢視子流程的輸出,可以使用以下程式碼段:

process = subprocess.Popen(<your_command>, stdout=subprocess.PIPE)
while process.poll() is None:
    output_line = process.stdout.readline()

如果子命令輸出沒有 EOL 字元,則上述程式碼段不起作用。然後,你可以按字元讀取輸出字元,如下所示:

process = subprocess.Popen(<your_command>, stdout=subprocess.PIPE)
while process.poll() is None:
    output_line = process.stdout.read(1)

指定為 read 方法的引數的 1 告訴 read 在時間讀取 1 個字元。你可以指定使用不同的數字讀取所需的字元數。負數或 0 告訴 read 讀取單個字串,直到遇到 EOF( 參見此處 )。

在上面的兩個片段中,process.poll() 都是 None,直到子程序完成。一旦沒有更多輸出要讀取,這用於退出迴圈。

相同的過程可以應用於子過程的 stderr