How to get both return code and output from subprocess in Python?
Question:
While developing python wrapper library for Android Debug Bridge (ADB), I’m using subprocess to execute adb commands in shell. Here is the simplified example:
import subprocess
...
def exec_adb_command(adb_command):
return = subprocess.call(adb_command)
If command executed propery exec_adb_command returns 0 which is OK.
But some adb commands return not only “0” or “1” but also generate some output which I want to catch also. adb devices for example:
D:gitadb-libtest>adb devices
List of devices attached
07eeb4bb device
I’ve already tried subprocess.check_output() for that purpose, and it does return output but not the return code (“0” or “1”).
Ideally I would want to get a tuple where t[0] is return code and t[1] is actual output.
Am I missing something in subprocess module which already allows to get such kind of results?
Thanks!
Answers:
Popen and communicate will allow you to get the output and the return code.
from subprocess import Popen,PIPE,STDOUT
out = Popen(["adb", "devices"],stderr=STDOUT,stdout=PIPE)
t = out.communicate()[0],out.returncode
print(t)
('List of devices attached nn', 0)
check_output may also be suitable, a non-zero exit status will raise a CalledProcessError:
from subprocess import check_output, CalledProcessError
try:
out = check_output(["adb", "devices"])
t = 0, out
except CalledProcessError as e:
t = e.returncode, e.message
You also need to redirect stderr to store the error output:
from subprocess import check_output, CalledProcessError
from tempfile import TemporaryFile
def get_out(*args):
with TemporaryFile() as t:
try:
out = check_output(args, stderr=t)
return 0, out
except CalledProcessError as e:
t.seek(0)
return e.returncode, t.read()
Just pass your commands:
In [5]: get_out("adb","devices")
Out[5]: (0, 'List of devices attached nn')
In [6]: get_out("adb","devices","foo")
Out[6]: (1, 'Usage: adb devices [-l]n')
While developing python wrapper library for Android Debug Bridge (ADB), I’m using subprocess to execute adb commands in shell. Here is the simplified example:
import subprocess
...
def exec_adb_command(adb_command):
return = subprocess.call(adb_command)
If command executed propery exec_adb_command returns 0 which is OK.
But some adb commands return not only “0” or “1” but also generate some output which I want to catch also. adb devices for example:
D:gitadb-libtest>adb devices
List of devices attached
07eeb4bb device
I’ve already tried subprocess.check_output() for that purpose, and it does return output but not the return code (“0” or “1”).
Ideally I would want to get a tuple where t[0] is return code and t[1] is actual output.
Am I missing something in subprocess module which already allows to get such kind of results?
Thanks!
Popen and communicate will allow you to get the output and the return code.
from subprocess import Popen,PIPE,STDOUT
out = Popen(["adb", "devices"],stderr=STDOUT,stdout=PIPE)
t = out.communicate()[0],out.returncode
print(t)
('List of devices attached nn', 0)
check_output may also be suitable, a non-zero exit status will raise a CalledProcessError:
from subprocess import check_output, CalledProcessError
try:
out = check_output(["adb", "devices"])
t = 0, out
except CalledProcessError as e:
t = e.returncode, e.message
You also need to redirect stderr to store the error output:
from subprocess import check_output, CalledProcessError
from tempfile import TemporaryFile
def get_out(*args):
with TemporaryFile() as t:
try:
out = check_output(args, stderr=t)
return 0, out
except CalledProcessError as e:
t.seek(0)
return e.returncode, t.read()
Just pass your commands:
In [5]: get_out("adb","devices")
Out[5]: (0, 'List of devices attached nn')
In [6]: get_out("adb","devices","foo")
Out[6]: (1, 'Usage: adb devices [-l]n')