I would like to get the output (print statements) and return status from a python subprocess along with displaying logging info. I am using Python 2.5 on Windows XP. How do I get the return code as well? Here in this extract, I am reading output so that I can redirect it to display in a wxPython TextCtrl
in a separate thread.
self.myproc.poll()
if self.myproc.returncode is None:
# Still running so check stdout
txt = self.myproc.stdout.read(self._readblock)
if txt:
# Add to UI's update queue
self._parent.AppendUpdate(txt)
else:
break
To capture the output of the subprocess. run method, use an additional argument named “capture_output=True”. You can individually access stdout and stderr values by using “output. stdout” and “output.
Description. Python method popen() opens a pipe to or from command. The return value is an open file object connected to the pipe, which can be read or written depending on whether mode is 'r' (default) or 'w'. The bufsize argument has the same meaning as in open() function.
check_call() returns as soon as /bin/sh process exits without waiting for descendant processes (assuming shell=True as in your case). check_output() waits until all output is read. If ssh inherits the pipe then check_output() will wait until it exits (until it closes its inherited pipe ends).
The returncode gets returned by the poll
call, and is also (once poll
did not return None
) accessible via the returncode
attribute. You are already using this in your code, so I'm not sure what your problem with that is.
When you want to update your control while your process is running, use readline
instead of read
: the latter will wait for the entire output to be present, while the former will wait on a newline character. To give a full example using your variable names:
from subprocess import Popen, PIPE
self.myproc = Popen('dir /s', shell=True, stdout=PIPE, stderr=PIPE)
while self.myproc.poll() == None:
self._parent.AppendUpdate(self.myproc.stdout.readline())
self._parent.AppendUpdate('Return code was ' + self.myproc.returncode)
Note that you might want to .strip()
the readline
result as it will contain the newline character.
Edit: To address your confusion between the script output and its return code, the following. First, a Python script at module level cannot return a value: that would yield a syntax error. So what you should differentiate between is the output of the script, and the return code it gives.
The script's output is in the above example read by using the self.myproc.stdout.readline
method. Every time the external process has produced a line of outputted text, calling that function would retrieve it.
The return code however (or exit status) is an integer that gets passed from a child process to the parent (your) process, indicating the state in which the child process exited. In Python, you do this with the sys.exit
function. Most commonly, when this value is zero it indicates success; a non-zero value depicts some kind of error.
Say your child process script looks like this:
import sys
# Do some stuff
print 'pass' # Gets to stdout
sys.exit(0) # Return code
Executing this external file (let's call it test.py
) with the Popen
class, we will get pass
when we read out self.myproc.stdout
, and 0
when we read out self.myproc.poll
(or self.myproc.returncode
after the first poll).
The purpose of this return code is that you do not have to parse all of the child process' output to determine if it succeeded in its job: you are free to define your own exit codes. For example, you could consider 0
to be a success, 1
to be a failure, 2
to be some kind of invalid input given, 9
an unknown error, and so on. That way, you can just keep poll
ing the process, and based on the exit code returned by that poll you directly know if it was successful. Note that this is a bit less applicable to your case as you need the output of the child process anyway, but still it is easier to parse a number than a string to determine success.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With