Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return value from Python subprocess

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     
like image 580
user974168 Avatar asked Nov 09 '11 05:11

user974168


People also ask

How do I get output to run from subprocess?

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.

What does Popen return Python?

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.

What is Check_call?

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).


1 Answers

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 polling 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.

like image 123
jro Avatar answered Oct 10 '22 17:10

jro