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?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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.
Method 2
.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.
Method 3
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.
Method 4
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.
Method 5
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)
Method 6
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 therun()function
for all use cases
it can handle.
For more advanced
use cases, the underlying
Popeninterface
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.
Method 7
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
Method 8
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:UsersshitaDocumentsTechPython>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
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0