Python subprocess get children's output to file and terminal?

后端 未结 2 1560
耶瑟儿~
耶瑟儿~ 2020-11-22 10:09

I\'m running a script that executes a number of executables by using

subprocess.call(cmdArgs,stdout=outf, stderr=errf)

when outf

相关标签:
2条回答
  • 2020-11-22 10:36

    You could use something like this: https://github.com/waszil/subpiper

    In your callbacks you can do whatever you like, log, write to file, print, etc. It also supports non-blocking mode.

    from subpiper import subpiper
    
    def my_stdout_callback(line: str):
        print(f'STDOUT: {line}')
    
    def my_stderr_callback(line: str):
        print(f'STDERR: {line}')
    
    my_additional_path_list = [r'c:\important_location']
    
    retcode = subpiper(cmd='echo magic',
                       stdout_callback=my_stdout_callback,
                       stderr_callback=my_stderr_callback,
                       add_path_list=my_additional_path_list)
    
    0 讨论(0)
  • 2020-11-22 10:49

    The call() function is just Popen(*args, **kwargs).wait(). You could call Popen directly and use stdout=PIPE argument to read from p.stdout:

    #!/usr/bin/env python
    import sys
    from subprocess import Popen, PIPE
    from threading import Thread
    
    
    def tee(infile, *files):
        """Print `infile` to `files` in a separate thread."""
    
        def fanout(infile, *files):
            with infile:
                for line in iter(infile.readline, b""):
                    for f in files:
                        f.write(line)
    
        t = Thread(target=fanout, args=(infile,) + files)
        t.daemon = True
        t.start()
        return t
    
    
    def teed_call(cmd_args, **kwargs):
        stdout, stderr = [kwargs.pop(s, None) for s in ["stdout", "stderr"]]
        p = Popen(
            cmd_args,
            stdout=PIPE if stdout is not None else None,
            stderr=PIPE if stderr is not None else None,
            **kwargs
        )
        threads = []
        if stdout is not None:
            threads.append(
                tee(p.stdout, stdout, getattr(sys.stdout, "buffer", sys.stdout))
            )
        if stderr is not None:
            threads.append(
                tee(p.stderr, stderr, getattr(sys.stderr, "buffer", sys.stderr))
            )
        for t in threads:
            t.join()  # wait for IO completion
        return p.wait()
    
    
    outf, errf = open("out.txt", "wb"), open("err.txt", "wb")
    assert not teed_call(["cat", __file__], stdout=None, stderr=errf)
    assert not teed_call(["echo", "abc"], stdout=outf, stderr=errf, bufsize=0)
    assert teed_call(["gcc", "a b"], close_fds=True, stdout=outf, stderr=errf)
    
    0 讨论(0)
提交回复
热议问题