你能像往常一样制作一个python子进程输出stdout和stderr,但也可以将输出捕获为字符串吗?
问题描述
可能重复:
包装子进程'stdout/stderr
在这个问题中,hanan-n 询问是否有可能有一个 python 子进程输出到标准输出,同时还将输出保存在一个字符串中以供以后处理.这种情况下的解决方案是遍历每个输出行并手动打印它们:
In this question, hanan-n asked whether it was possible to have a python subprocess that outputs to stdout while also keeping the output in a string for later processing. The solution in this case was to loop over every output line and print them manually:
output = []
p = subprocess.Popen(["the", "command"], stdout=subprocess.PIPE)
for line in iter(p.stdout.readline, ''):
print(line)
output.append(line)
但是,此解决方案并不适用于您希望同时为 stdout 和 stderr 执行此操作的情况,同时满足以下条件:
However, this solution doesn't generalise to the case where you want to do this for both stdout and stderr, while satisfying the following:
- stdout/stderr 的输出应该分别到父进程的stdout/stderr
- 输出应尽可能实时完成(但我只需要访问最后的字符串)
- 不应更改 stdout 和 stderr 行之间的顺序(我不太确定如果子进程以不同的时间间隔刷新其 stdout 和 stderr 缓存,这将如何工作;让我们现在假设我们将所有内容都放在很好的块中包含完整的行?)
我查看了 子流程文档,但找不到任何可以做到这一点.我能找到的最接近的方法是添加 stderr=subprocess.stdout
并使用与上面相同的解决方案,但是我们失去了常规输出和错误之间的区别.有任何想法吗?我猜测解决方案 - 如果有的话 - 将涉及对 p.stdout
和 p.stderr
进行异步读取.
I looked through the subprocess documentation, but couldn't find anything that can achieve this. The closest I could find is to add stderr=subprocess.stdout
and use the same solution as above, but then we lose the distinction between regular output and errors. Any ideas? I'm guessing the solution - if there is one - will involve having asynchronous reads to p.stdout
and p.stderr
.
这是我想做的一个例子:
Here is an example of what I would like to do:
p = subprocess.Popen(["the", "command"])
p.wait() # while p runs, the command's stdout and stderr should behave as usual
p_stdout = p.stdout.read() # unfortunately, this will return '' unless you use subprocess.PIPE
p_stderr = p.stderr.read() # ditto
[do something with p_stdout and p_stderr]
解决方案
这个例子似乎对我有用:
This example seems to work for me:
# -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4
import subprocess
import sys
import select
p = subprocess.Popen(["find", "/proc"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout = []
stderr = []
while True:
reads = [p.stdout.fileno(), p.stderr.fileno()]
ret = select.select(reads, [], [])
for fd in ret[0]:
if fd == p.stdout.fileno():
read = p.stdout.readline()
sys.stdout.write('stdout: ' + read)
stdout.append(read)
if fd == p.stderr.fileno():
read = p.stderr.readline()
sys.stderr.write('stderr: ' + read)
stderr.append(read)
if p.poll() != None:
break
print 'program ended'
print 'stdout:', "".join(stdout)
print 'stderr:', "".join(stderr)
一般来说,在任何情况下,如果您想同时处理多个文件描述符并且您不知道哪个有内容供您阅读,您应该使用 select 或类似的东西(例如 Twisted reactor).
In general, any situation where you want to do stuff with multiple file descriptors at the same time and you don't know which one will have stuff for you to read, you should use select or something equivalent (like a Twisted reactor).
相关文章