255

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?

0

8 Answers 8

362

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.

Sign up to request clarification or add additional context in comments.

6 Comments

This example helped me, but it would be nice if examples didn't do the "import subprocess as sp" pattern of importing something standard as an obscure abbreviation. While this trims 8 characters off the code that follows it, it also makes it difficult to understand and reuse.
@uglycoyote There's no rule that says you have to copy and paste. Just retype it however you want, it's like 4 like lines.
@uglycoyote you could also edit it to be something like from subprocess import Popen and then just use Popen instead of subprocess(or sp).Popen which I'd say probably increases readability and shortens lines
Yeah... must call process.communicate() and then assign returncode to some variable. If the assignment is done before calling communicate, is None.
Is it possible to show the return code without redirecting the pipe? I am calling a bash code and I would like to see the output in real time in the terminal
|
32

Just to point out a common misconception, you should avoid Popen always when you can. To quote the documentation,

The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly.

If you just want to run a subprocess and wait for it to finish, that's a single line of code with subprocess.run or its legacy siblings subprocess.call and subprocess.check_output, and you don't need to copy/paste and/or understand the intricacies of the communicate and wait etc methods required around the low-level Popen object.

import subprocess

proc = subprocess.run(
    [openRTSP] + opts.split(),
    capture_output=True,
    # avoid having to explicitly encode
    text=True)
data = proc.stdout
result = proc.returncode

If you don't want to capture the output from the process, maybe replace capture_output=True with stdout=subprocess.DEVNULL (and perhaps similarly for stderr); in the absence of either, the output will simply be displayed to the user, outside of Python's control.

Also, unless your options in opts are completely trivial, generally replace the regular string split() here with shlex.split() which understands how to cope with quoted strings.

Comments

23

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

3 Comments

when I did this .poll() was empty. I had to run child.communicate() in the line above child.poll() for this to work.
I think you meant to use .wait() instead of .poll(), as per documentation: docs.python.org/3/library/subprocess.html. Note that .wait() takes an optional timeout param which can be convenient.
poll() will only update the return code if the child has terminated, otherwise it will return None - wait() is better here.
19

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.

1 Comment

.communicate() already waits for the subprocess to terminate.
14

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)

Comments

8

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.

Comments

0

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 Comment

You can't meaningfully wait more than once.
-2

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

1 Comment

You can't communicate after wait.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.