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
对正在运行的子进程的交互式访问
即使子进程尚未完成,你也可以在 stdin
和 stdout
上进行读写。当在另一个程序中自动执行功能时,这可能很有用。
写入子进程
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()
而不是直接访问 stdin
和 stdout
。
从子进程读取流
如果你想逐行查看子流程的输出,可以使用以下代码段:
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
。