gpt4 book ai didi

python - 如何使用 Python 调用命令,捕获 stderr 和 stdout,而不等待 stderr/stdout 关闭?

转载 作者:太空宇宙 更新时间:2023-11-03 11:53:03 26 4
gpt4 key购买 nike

现在我有一些使用 Popen.communicate() 的代码从子进程(设置 stdin=PIPEstderr=PIPE)运行命令并捕获 stderr 和 stdout。

问题在于 communicate() 不仅等待命令退出,还等待 stdout 和 stderr 关闭。我正在运行的命令生成了一个子进程,它使 stderr 保持打开状态,因此即使该命令已完成运行(并在 ps 中显示为“defunct”)communicate() 仍然挂起。

我只想等待命令完成而不等待 stderr/stdout。但我仍然想捕获命令运行时给出的任何 stderr/stdout 输出。 The documentation for wait()附有免责声明的红框:

This will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.

显然,我也想避免死锁。

完成这项任务的正确方法是什么?

最佳答案

“在 ps 中显示为“defunct”” 暗示您可能在 selectfcntl 可以工作的系统上,即,您可以轻松读取 stdout/stderr 而不会阻塞。

示例:A 启动 B(cmd, child ),B 启动 C(孙子),A 读取输出直到 B 退出或 EOF:

#!/usr/bin/env python
import os
from select import select
from subprocess import Popen, PIPE

p = Popen(cmd, stdout=PIPE, stderr=PIPE, bufsize=0)
read_set = [p.stdout, p.stderr]
pipename = {p.stdout: "stdout", p.stderr: "stderr"}
timeout = 0.5 # ugly but it works
while read_set and p.poll() is None: # while subprocess is running or until EOF
for pipe in select(read_set, [], [], timeout)[0]:
data = os.read(pipe.fileno(), 1<<30)
if data:
print("got from %s: %r" % (pipename[pipe], data))
else: # EOF
pipe.close()
read_set.remove(pipe)
print("exit code %s" % (p.wait(),))

# child exited, wait for grandchild to print
for pipe in read_set:
print("read the rest of %s: %r" % (pipename[pipe], pipe.read()))
pipe.close()

哪里 cmd:

import sys
from textwrap import dedent

cmd = [sys.executable, '-u', '-c', dedent("""
# inception style
import os
import sys
from subprocess import Popen
from textwrap import dedent

Popen([sys.executable, '-u', '-c', dedent('''
import os
import sys
import time

time.sleep(60)
print("grandchild %d done" % os.getpid())
sys.stderr.write("grandchild stderr")
sys.exit(20)
''')]) # stdout/stderr are not redirected

print('child %d done' % os.getpid())
sys.stderr.write('child stderr')
sys.exit(19)
""")]

关于python - 如何使用 Python 调用命令,捕获 stderr 和 stdout,而不等待 stderr/stdout 关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21143587/

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