Reputation: 5660
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?
Upvotes: 255
Views: 425876
Reputation: 189789
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 underlyingPopen
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.
Upvotes: 31
Reputation: 1304
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
Upvotes: -2
Reputation: 34237
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)
Upvotes: 14
Reputation: 17
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
Upvotes: 0
Reputation: 355
.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
.
Upvotes: 22
Reputation: 273696
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
.
Upvotes: 362
Reputation: 72815
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.
Upvotes: 19
Reputation: 28703
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.
Upvotes: 8