Read streaming input from subprocess.communicate()

后端 未结 7 914
攒了一身酷
攒了一身酷 2020-11-21 05:53

I\'m using Python\'s subprocess.communicate() to read stdout from a process that runs for about a minute.

How can I print out each line of that process

7条回答
  •  执笔经年
    2020-11-21 06:03

    To get subprocess' output line by line as soon as the subprocess flushes its stdout buffer:

    #!/usr/bin/env python2
    from subprocess import Popen, PIPE
    
    p = Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1)
    with p.stdout:
        for line in iter(p.stdout.readline, b''):
            print line,
    p.wait() # wait for the subprocess to exit
    

    iter() is used to read lines as soon as they are written to workaround the read-ahead bug in Python 2.

    If subprocess' stdout uses a block buffering instead of a line buffering in non-interactive mode (that leads to a delay in the output until the child's buffer is full or flushed explicitly by the child) then you could try to force an unbuffered output using pexpect, pty modules or unbuffer, stdbuf, script utilities, see Q: Why not just use a pipe (popen())?


    Here's Python 3 code:

    #!/usr/bin/env python3
    from subprocess import Popen, PIPE
    
    with Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1,
               universal_newlines=True) as p:
        for line in p.stdout:
            print(line, end='')
    

    Note: Unlike Python 2 that outputs subprocess' bytestrings as is; Python 3 uses text mode (cmd's output is decoded using locale.getpreferredencoding(False) encoding).

提交回复
热议问题