gpt4 book ai didi

Python Popen - 等待与通信与 CalledProcessError

转载 作者:太空狗 更新时间:2023-10-30 00:40:07 24 4
gpt4 key购买 nike

继续 from my previous question我看到要获取我在 python 中通过 Popen 生成的进程的错误代码,我必须调用 wait() 或 communicate() (可用于访问 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() 可能溢出。所以:

  1. 在这里使用什么是正确的?请注意,我确实使用了输出
  2. 我应该如何使用 communicate ?会不会是:

    process = Popen(command, stdout=PIPE, startupinfo=startupinfo)
    out = process.communicate()[0]
    # same as before...
    result = process.returncode
    if result: # ...

    不确定阻塞和内存错误

  3. 任何更好/更 pythonic 的方法来处理这个问题?我不认为subprocess.CalledProcessError or the subprocess.check_call/check_output适用于我的情况 - 还是适用?

免责声明:我没有编写代码,我是当前的维护者,因此是问题 3。

相关:

如果这有所不同,我在 Windows 上 - python 2.7.8

应该有一种——最好只有一种——显而易见的方法来做到这一点

最佳答案

  • 关于死锁:将stdout=PIPEwait() 一起使用是安全的iff 您从管道读取。 .communicate() 为您读取并调用 wait()
  • 关于内存:如果输出可以是无限的,那么你不应该使用 .communicate() 来累积内存中的所有输出。

what is the proper thing to use here ?

要启动子进程,逐行读取它的输出并等待它退出:

#!/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()

此代码不会因操作系统管道缓冲区有限而死锁。此外,该代码支持具有无限输出的命令(如果单独的一行适合内存)。

iter() 用于在刷新子进程的标准输出缓冲区后立即读取一行,解决方法 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()

There should be one-- and preferably only one --obvious way to do it

subprocess.Popen() 是适用于许多情况的主要 API。对于常见用例,有一些方便的函数/方法,例如 Popen.communicate()check_output()check_call()

有多种方法和功能,因为有多种不同的用例。

关于Python Popen - 等待与通信与 CalledProcessError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30982217/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com