继续from my previous question我看到要获取我在python中通过Popen生成的进程的错误代码我必须调用wait()或communic()(可以用来访问Popen stdout和stderr)属性):
app7z = '/path/to/7z.exe'
command = [app7z, 'a', dstFile.temp, "-y", "-r", os.path.join(src.Dir, '*')]
process = Popen(command, stdout=PIPE, startupinfo=startupinfo)
out = process.stdout
regCompressMatch = re.compile('Compressing\s+(.+)').match
regErrMatch = re.compile('Error: (.*)').match
errorLine = []
for line in out:
if len(errorLine) or regErrMatch(line):
errorLine.append(line)
if regCompressMatch(line):
# update a progress bar
result = process.wait() # HERE
if result: # in the hopes that 7z returns 0 for correct execution
dstFile.temp.remove()
raise StateError(_("%s: Compression failed:\n%s") % (dstFile.s,
"\n".join(errorLine)))
但是the docs警告wait()
可能会死锁(当stdout = PIPE时,就是这里的情况),而communicate()
可能会溢出。所以:
我应该如何使用沟通?它会是:
process = Popen(command, stdout=PIPE, startupinfo=startupinfo)
out = process.communicate()[0]
# same as before...
result = process.returncode
if result: # ...
不确定阻止和内存错误
subprocess.CalledProcessError
or the subprocess.check_call/check_output
适用于我的情况 - 或者是吗?免责声明:我没有编写代码,我是当前的维护者,因此问题3。
相关:
如果这有所不同,我在Windows上 - python 2.7.8
应该有一个 - 最好只有一个 - 显而易见的方法
答案 0 :(得分:10)
stdout=PIPE
和wait()
一起 iff 从管道中读取。 .communicate()
执行阅读并为您致电wait()
.communicate()
。在这里使用什么是正确的?
要启动子进程,请逐行读取其输出并等待它退出:
#!/usr/bin/env python
from subprocess import Popen, PIPE
process = Popen(command, stdout=PIPE, bufsize=1)
with process.stdout:
for line in iter(process.stdout.readline, b''):
handle(line)
returncode = process.wait()
由于有限的OS管道缓冲区,此代码不会死锁。此外,代码支持无限输出的命令(如果单个行适合内存)。
iter()
用于在子流程'之后立即读取一行。刷新stdout缓冲区,以解决方法the read-ahead bug in Python 2。如果您在编写行时不需要读取行而不等待缓冲区填充或子进程结束,则可以使用简单的for line in process.stdout
。请参阅Python: read streaming input from subprocess.communicate()。
如果知道命令输出在所有情况下都可以适合内存,那么你可以一次获得输出:
#!/usr/bin/env python
from subprocess import check_output
all_output = check_output(command)
如果命令以非零退出状态返回,则引发CalledProcessError
。在内部,check_output()
uses Popen()
and .communicate()
应该有一个 - 最好只有一个 - 显而易见的方法
subprocess.Popen()
是在很多情况下都可以使用的主要API。对于常见用例,有Popen.communicate()
,check_output()
,check_call()
等便捷功能/方法。
有多种方法,功能因为有多种不同的用例。