首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >合并Python脚本子进程的stdout和stderr,同时保持它们的可区分性

合并Python脚本子进程的stdout和stderr,同时保持它们的可区分性
EN

Stack Overflow用户
提问于 2011-07-25 04:43:09
回答 6查看 20.2K关注 0票数 44

我想将python脚本子进程的stdout和stdin定向到同一个文件中。我不知道的是如何区分这两个来源的代码行?(例如,在stderr中的行前加上感叹号。)

在我的特殊情况下,不需要实时监控子进程,正在执行的Python脚本可以等待其执行结束。

EN

回答 6

Stack Overflow用户

发布于 2011-10-03 06:28:04

代码语言:javascript
复制
tsk = subprocess.Popen(args,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)

subprocess.STDOUT是一个特殊的标志,它告诉子进程将所有stderr输出路由到stdout,从而将两个流组合在一起。

顺便说一句,select在windows中没有poll()。子进程只使用文件句柄编号,并不调用文件输出对象的write方法。

要捕获输出,请执行以下操作:

代码语言:javascript
复制
logfile = open(logfilename, 'w')

while tsk.poll() is None:
    line = tsk.stdout.readline()
    logfile.write(line)
票数 59
EN

Stack Overflow用户

发布于 2012-03-28 08:52:40

我发现自己最近不得不解决这个问题,而且花了一段时间才得到我认为在大多数情况下都能正常工作的东西,所以就是这样!(它还有一个很好的副作用,可以通过python日志记录器处理输出,我注意到这是Stackoverflow上的另一个常见问题)。

代码如下:

代码语言:javascript
复制
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

下面是输出:

代码语言:javascript
复制
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。否则,您可能会阻止读取一个,而在另一个上有准备读取的数据。

票数 13
EN

Stack Overflow用户

发布于 2011-07-25 06:41:25

如果您希望交错以获得与以交互方式运行进程的顺序大致相同的顺序,那么您需要执行shell所做的操作,轮询stdin/stdout并按照轮询的顺序写入。

下面的代码完成了您想要做的事情--在本例中,将stdout/stderr发送到一个记录器信息/错误流。

代码语言:javascript
复制
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()
票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6809590

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档