Streaming read from subprocess Streaming read from subprocess python-3.x python-3.x

Streaming read from subprocess


subprocess.run always spawns the child process, and blocks the thread until it exits.

The only option for you is to use p = subprocess.Popen(...) and read lines with s = p.stdout.readline() or p.stdout.__iter__() (see below).

This code works for me, if the child process flushes stdout after printing a line (see below for extended note).

cmd = ["/usr/bin/python3", "zzz.py"]test_proc = subprocess.Popen(    cmd,    stdout=subprocess.PIPE,    stderr=subprocess.STDOUT)out_data = ""print(time.time(), "START")while not "QUIT" in str(out_data):    out_data = test_proc.stdout.readline()    print(time.time(), "MAIN received", out_data)test_proc.communicate()  # shut it down

See my terminal log (dots removed from zzz.py):

ibug@ubuntu:~/t $ python3 p.py1546450821.9174328 START1546450821.9793346 MAIN received b'0 sleeping \n'1546450822.987753 MAIN received b'1 sleeping \n'1546450823.993136 MAIN received b'2 sleeping \n'1546450824.997726 MAIN received b'3 sleeping \n'1546450825.9975247 MAIN received b'4 sleeping \n'1546450827.0094354 MAIN received b'QUIT this exercise\n'

You can also do it with a for loop:

for out_data in test_proc.stdout:    if "QUIT" in str(out_data):        break    print(time.time(), "MAIN received", out_data)

If you cannot modify the child process, unbuffer (from package expect - install with APT or YUM) may help. This is my working parent code without changing the child code.

test_proc = subprocess.Popen(    ["unbuffer"] + cmd,    stdout=subprocess.PIPE,    stderr=subprocess.STDOUT)