208
votes

How do I retrieve the exit code when using Python's subprocess module and the communicate() method?

Relevant code:

import subprocess as sp
data = sp.Popen(openRTSP + opts.split(), stdout=sp.PIPE).communicate()[0]

Should I be doing this another way?

7

7 Answers

300
votes

Popen.communicate will set the returncode attribute when it's done(*). Here's the relevant documentation section:

Popen.returncode 
  The child return code, set by poll() and wait() (and indirectly by communicate()). 
  A None value indicates that the process hasn’t terminated yet.

  A negative value -N indicates that the child was terminated by signal N (Unix only).

So you can just do (I didn't test it but it should work):

import subprocess as sp
child = sp.Popen(openRTSP + opts.split(), stdout=sp.PIPE)
streamdata = child.communicate()[0]
rc = child.returncode

(*) This happens because of the way it's implemented: after setting up threads to read the child's streams, it just calls wait.

15
votes

.poll() will update the return code.

Try

child = sp.Popen(openRTSP + opts.split(), stdout=sp.PIPE)
returnCode = child.poll()

In addition, after .poll() is called the return code is available in the object as child.returncode.

13
votes

You should first make sure that the process has completed running and the return code has been read out using the .wait method. This will return the code. If you want access to it later, it's stored as .returncode in the Popen object.

7
votes

exitcode = data.wait(). The child process will be blocked If it writes to standard output/error, and/or reads from standard input, and there are no peers.

1
votes

This worked for me. It also prints the output returned by the child process

child = subprocess.Popen(serial_script_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    retValRunJobsSerialScript = 0
    for line in child.stdout.readlines():
        child.wait()
        print line           
    retValRunJobsSerialScript= child.returncode
1
votes

Use process.wait() after you call process.communicate().
For example:

import subprocess

process = subprocess.Popen(['ipconfig', '/all'], stderr=subprocess.PIPE, stdout=subprocess.PIPE)
stdout, stderr = process.communicate()
exit_code = process.wait()
print(stdout, stderr, exit_code)
0
votes

Please see the comments.

Code:

import subprocess


class MyLibrary(object):

    def execute(self, cmd):
        return subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True,)
      
    def list(self):
        command = ["ping", "google.com"]
        sp = self.execute(command)
        status = sp.wait()  # will wait for sp to finish
        out, err = sp.communicate()
        print(out)
        return status # 0 is success else error


test = MyLibrary()

print(test.list())

Output:

C:\Users\shita\Documents\Tech\Python>python t5.py

Pinging google.com [142.250.64.78] with 32 bytes of data:
Reply from 142.250.64.78: bytes=32 time=108ms TTL=116
Reply from 142.250.64.78: bytes=32 time=224ms TTL=116
Reply from 142.250.64.78: bytes=32 time=84ms TTL=116
Reply from 142.250.64.78: bytes=32 time=139ms TTL=116

Ping statistics for 142.250.64.78:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 84ms, Maximum = 224ms, Average = 138ms

0