可以分别记录正在运行的程序的stdout和stderr。
您无法使用,
pexpect因为stdout和stderr都使用相同的
pty方法,之后无法将它们分开。
可以实时查看正在运行的程序的stdout和stderr,这样,如果子进程挂起,则用户可以看到。(即,我们不等待执行完成再将stdout /
stderr打印给用户)
如果子进程的输出不是tty
,则可能使用块缓冲,因此,如果子进程的输出不大
,则不会是“实时”,
例如,如果缓冲区为4K,则您的父级直到子进程打印4K字符并且缓冲区溢出或显式刷新(在子进程内部),Python进程才会看到任何内容。该缓冲区位于子进程内部,没有标准的方法可以从外部进行管理。这是显示stdio缓冲区和
command1 | command2shell管道的管道缓冲区的图片:
正在运行的程序不知道它是通过python运行的,因此不会做意外的事情(例如,将其输出分块而不是实时打印,或者退出,因为它需要一个终端来查看其输出)。
看来,您的意思相反,即,如果将输出重定向到管道(
stdout=PIPE在Python中使用),则子进程可能会对其输出进行分块,而不是尽快刷新每条输出行。这意味着默认的线程或异步解决方案将无法正常使用。
有几种解决方法:
该命令可以接受诸如
grep --line-buffered
或的命令行参数python -u
来禁用块缓冲。stdbuf
适用于某些程序,即,您可以['stdbuf', '-oL', '-eL'] + command
使用上面的线程或asyncio解决方案运行,并且应该分别获得stdout,stderr和行,并且这些行应几乎实时显示:#!/usr/bin/env python3
import os
import sys
from select import select
from subprocess import Popen, PIPEwith Popen([‘stdbuf’, ‘-oL’, ‘-e0’, ‘curl’, 'www.google.com’],
stdout=PIPE, stderr=PIPE) as p:
readable = {
p.stdout.fileno(): sys.stdout.buffer, # log separately
p.stderr.fileno(): sys.stderr.buffer,
}
while readable:
for fd in select(readable, [], [])[0]:
data = os.read(fd, 1024) # read available
if not data: # EOF
del readable[fd]
else:
readable[fd].write(data)
readable[fd].flush()最后,您可以尝试使用
pty
+select
两个解决方案pty
:#!/usr/bin/env python3
import errno
import os
import pty
import sys
from select import select
from subprocess import Popenmasters, slaves = zip(pty.openpty(), pty.openpty())
with Popen([sys.executable, ‘-c’, r’‘’import sys, time
print(‘stdout’, 1) # no explicit flush
time.sleep(.5)
print(‘stderr’, 2, file=sys.stderr)
time.sleep(.5)
print(‘stdout’, 3)
time.sleep(.5)
print(‘stderr’, 4, file=sys.stderr)
‘’‘],
stdin=slaves[0], stdout=slaves[0], stderr=slaves[1]):
for fd in slaves:
os.close(fd) # no input
readable = {
masters[0]: sys.stdout.buffer, # log separately
masters[1]: sys.stderr.buffer,
}
while readable:
for fd in select(readable, [], [])[0]:
try:
data = os.read(fd, 1024) # read available
except OSError as e:
if e.errno != errno.EIO:
raise #XXX cleanup
del readable[fd] # EIO means EOF on some systems
else:
if not data: # EOF
del readable[fd]
else:
readable[fd].write(data)
readable[fd].flush()
for fd in masters:
os.close(fd)
我不知道
pty对stdout,stderr使用不同的s有什么副作用。您可以尝试在您的情况下
stderr=PIPE使用一个pty是否足够,例如,设置并使用
p.stderr.fileno()代替
masters[1]。来源中的评论
sh表明,如果
stderrnot in {STDOUT,pipe}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)