Reputation: 675
Is it possible to read a subprocess's stdout
but at the end of the program still maintain the whole process.communicate()
?
For example i have a python script that starts a c# app in a Popen
subprocess and checks the log file it produces live to determine the state it is in but certain errors are not dumped in the logs and are in the stdout
and certain errors there will cause the process to hang. I want to be able to detect that output and in those cases be able to kill the process.
This is easy while doing process.stdout.readline()
but at the end of the program i loose the ability to dump the entire stdout in it's native formatting because the buffer get's flushed after reading. Is it possible to maintain that buffer?
Or at the very least save the read lines in a variable in it's native formatting?
Upvotes: 0
Views: 1433
Reputation: 77337
You can read stdout line by line, process it and save it to a list or buffer, and have the buffer available later. In this example processing is just print
, but you could change that however you want. I also assumed you just want to collect stderr in the background, so created a separate thread.
import subprocess as subp
import threading
import io
def _pipe_read_thread(stream, output):
output.write(stream.read())
stream.close()
def proc_runner(cmd):
stdout_lines = []
stdout_buf = io.BytesIO()
stderr_buf = io.BytesIO()
p = subp.Popen(cmd, stdout=subp.PIPE, stderr=subp.PIPE)
stderr_t = threading.Thread(target=_pipe_read_thread,
args=(p.stderr, stderr_buf))
stderr_t.start()
for line in p.stdout:
print(line)
stdout_buf.write(line)
returncode = p.wait()
stderr_t.join()
stdout_buf. seek(0)
stderr_buf.seek(0)
return returncode, stdout_buf, stderr_buf
returncode, stdout, stderr = proc_runner(['ls', '-a'])
print('=============================')
print(stdout.read())
print('=============================')
print(stderr.read())
Upvotes: 2