我想将python脚本子进程的stdout和stdin定向到同一个文件中。我不知道的是如何区分这两个来源的代码行?(例如,在stderr中的行前加上感叹号。)
在我的特殊情况下,不需要实时监控子进程,正在执行的Python脚本可以等待其执行结束。
发布于 2011-10-03 06:28:04
tsk = subprocess.Popen(args,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)subprocess.STDOUT是一个特殊的标志,它告诉子进程将所有stderr输出路由到stdout,从而将两个流组合在一起。
顺便说一句,select在windows中没有poll()。子进程只使用文件句柄编号,并不调用文件输出对象的write方法。
要捕获输出,请执行以下操作:
logfile = open(logfilename, 'w')
while tsk.poll() is None:
line = tsk.stdout.readline()
logfile.write(line)发布于 2012-03-28 08:52:40
我发现自己最近不得不解决这个问题,而且花了一段时间才得到我认为在大多数情况下都能正常工作的东西,所以就是这样!(它还有一个很好的副作用,可以通过python日志记录器处理输出,我注意到这是Stackoverflow上的另一个常见问题)。
代码如下:
import sys
import logging
import subprocess
from threading import Thread
logging.basicConfig(stream=sys.stdout,level=logging.INFO)
logging.addLevelName(logging.INFO+2,'STDERR')
logging.addLevelName(logging.INFO+1,'STDOUT')
logger = logging.getLogger('root')
pobj = subprocess.Popen(['python','-c','print 42;bargle'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def logstream(stream,loggercb):
while True:
out = stream.readline()
if out:
loggercb(out.rstrip())
else:
break
stdout_thread = Thread(target=logstream,
args=(pobj.stdout,lambda s: logger.log(logging.INFO+1,s)))
stderr_thread = Thread(target=logstream,
args=(pobj.stderr,lambda s: logger.log(logging.INFO+2,s)))
stdout_thread.start()
stderr_thread.start()
while stdout_thread.isAlive() and stderr_thread.isAlive():
pass下面是输出:
STDOUT:root:42
STDERR:root:Traceback (most recent call last):
STDERR:root: File "<string>", line 1, in <module>
STDERR:root:NameError: name 'bargle' is not defined您可以替换子进程调用来做任何您想做的事情,我只是选择使用一个我知道会打印到stdout和stderr的命令来运行python。密钥位是在单独的线程中读取stderr和stdout。否则,您可能会阻止读取一个,而在另一个上有准备读取的数据。
发布于 2011-07-25 06:41:25
如果您希望交错以获得与以交互方式运行进程的顺序大致相同的顺序,那么您需要执行shell所做的操作,轮询stdin/stdout并按照轮询的顺序写入。
下面的代码完成了您想要做的事情--在本例中,将stdout/stderr发送到一个记录器信息/错误流。
tsk = subprocess.Popen(args,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
poll = select.poll()
poll.register(tsk.stdout,select.POLLIN | select.POLLHUP)
poll.register(tsk.stderr,select.POLLIN | select.POLLHUP)
pollc = 2
events = poll.poll()
while pollc > 0 and len(events) > 0:
for event in events:
(rfd,event) = event
if event & select.POLLIN:
if rfd == tsk.stdout.fileno():
line = tsk.stdout.readline()
if len(line) > 0:
logger.info(line[:-1])
if rfd == tsk.stderr.fileno():
line = tsk.stderr.readline()
if len(line) > 0:
logger.error(line[:-1])
if event & select.POLLHUP:
poll.unregister(rfd)
pollc = pollc - 1
if pollc > 0: events = poll.poll()
tsk.wait()https://stackoverflow.com/questions/6809590
复制相似问题