我有一个python子进程,我正在尝试从中读取输出和错误流。目前,我可以使用它,但是只能从stderr
中读取后,才能从stdout
中读取。看起来是这样的:
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout_iterator = iter(process.stdout.readline, b"")
stderr_iterator = iter(process.stderr.readline, b"")
for line in stdout_iterator:
# Do stuff with line
print line
for line in stderr_iterator:
# Do stuff with line
print line
如您所见,
stderr
for循环在stdout
循环完成之前无法启动。我如何修改它以便能够以正确的顺序从行中读取两者?需要说明的是:我仍然需要能够区分一行是
stdout
还是stderr
,因为它们在我的代码中将被区别对待。 最佳答案
这是一种基于selectors
的解决方案,但该解决方案保留顺序并流变长字符(甚至是单个字符)。
诀窍是使用 read1()
而不是read()
。
import selectors
import subprocess
import sys
p = subprocess.Popen(
["python", "random_out.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
sel = selectors.DefaultSelector()
sel.register(p.stdout, selectors.EVENT_READ)
sel.register(p.stderr, selectors.EVENT_READ)
while True:
for key, _ in sel.select():
data = key.fileobj.read1().decode()
if not data:
exit()
if key.fileobj is p.stdout:
print(data, end="")
else:
print(data, end="", file=sys.stderr)
如果您需要测试程序,请使用它。
import sys
from time import sleep
for i in range(10):
print(f" x{i} ", file=sys.stderr, end="")
sleep(0.1)
print(f" y{i} ", end="")
sleep(0.1)