简体   繁体   English

如何捕获通过管道流程生成的子流程的输出?

[英]How can I capture the output of a child process spawned by a piped process?

I want to continuously monitor a piped process and print its stdout and stderr as it comes in ( I'm not interested in getting the whole output all at once after it exited ). 我想不断监视管道进程并在其进入​​时打印其stdoutstderr (我对退出后立即全部获取全部输出不感兴趣)。 The problem is that the piped process spawns an other child process, and the stdout and stderr of that spawned process is not accessible using the pipes of the original process. 问题在于,管道处理产生了另一个子进程,并且使用原始进程的管道无法访问该产生的进程的stdoutstderr

Namely I want to run a python program in this way, so the piped process is the python interpreter, but python interpreter spawns the running of the python program in an other subprocess, so I can't obtain the output of that ( the actual program output ). 也就是说,我想以这种方式运行python程序,因此管道进程是python解释器,但是python解释器会在另一个子进程中生成python程序的运行,因此我无法获得该输出(实际程序输出)。 If there is an error starting the program, I can get this because this is printed to original python interpreter's stderr . 如果启动程序时出错,我可以得到它,因为它被打印到原始python解释器的stderr But normal stdout from the actual program is lost for me. 但是实际程序中的正常stdout对我来说却丢失了。

I'm using subprocess.Popen . 我正在使用subprocess.Popen

Edit: A commenter asked for a code sample, I don't think this adds to much, but here is my code ( PopenProcess is an intelligent wrapper class for subrpocess.Popen but does nothing extraordinary ): 编辑:一个评论者问了代码示例,我不认为这会增加很多,但这里是我的代码( 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()

As a piped process instead of 作为管道处理而不是

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

one should use 一个应该使用

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

Then it works. 然后就可以了。

The problem was with buffered output, and -u switch turns this off ( allows unbuffered output ). 问题出在缓冲输出上,而-u开关将其关闭(允许无缓冲输出)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM