简体   繁体   中英

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 ). 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.

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 ). If there is an error starting the program, I can get this because this is printed to original python interpreter's stderr . But normal stdout from the actual program is lost for me.

I'm using 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 ):

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 ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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