首页 > 解决方案 > 如何捕获由管道进程产生的子进程的输出?

问题描述

我想持续监控一个管道进程并在它进入时打印它stdoutstderr我对退出后立即获取整个输出不感兴趣)。问题是管道进程生成了另一个子进程,并且使用原始进程的管道无法访问该生成进程的stdoutand 。stderr

即我想以这种方式运行一个python程序,所以管道进程是python解释器,但是python解释器在另一个子进程中产生了python程序的运行,所以我无法获得它的输出(实际程序输出 )。如果启动程序出错,我可以得到这个,因为这是打印到原始 python 解释器的stderr. 但是stdout实际程序中的正常情况对我来说是丢失的。

我正在使用subprocess.Popen.

编辑:评论者要求提供代码示例,我认为这不会增加太多,但这是我的代码(PopenProcess是一个智能包装类,subrpocess.Popen但没有什么特别之处):

class BTask:
    def __init__(self, name, cmds, color = "NONE"):
        self.name = name
        self.cmds = cmds
        self.color = color
        self.proc = None

    def procreadline(self, sline):
        print(ANSI[self.color] + self.name + ANSI["ENDC"] + " > " + ANSI[self.color] + sline)

    def procreaderror(self, sline):
        print(ANSI[self.color] + self.name + ANSI["BRIGHTWHITE"] + " ! " + ANSI["BRIGHTRED"] + sline)

    def run(self):        
        print(ANSI["GREEN"])
        print("running task: {} {}".format(ANSI["BRIGHTGREEN"], self.name))
        pargs = []
        if len(self.cmds) > 1:
            pargs = self.cmds[1:]        
        print(ANSI[self.color])
        self.proc = PopenProcess(
            self.cmds[0],
            self.procreadline,
            read_error_callback = self.procreaderror,
            proc_args = pargs,
            ignore_cwd = True
            )

    def kill(self):
        print(ANSI["RED"])
        print("killing task: {} {}".format(ANSI["BRIGHTRED"], self.name))
        self.proc.kill()

    def is_alive():
        return self.proc.is_alive()

标签: pythonsubprocesspipestdout

解决方案


作为管道进程而不是

subprocess.Popen(['python', 'myprog.py'])

应该使用

subprocess.Popen(['python', '-u', 'myprog.py'])

然后它工作。

问题出在缓冲输出上,-u开关将其关闭(允许无缓冲输出)。


推荐阅读