Python tip 11: capture external command output
The subprocess
module provides plethora of features to execute external commands, capturing output being one of them. There are two ways to do so:
- passing
capture_output=True
tosubprocess.run()
subprocess.check_output()
if you only wantstdout
By default, results are provided as bytes
data type. You can change that by passing text=True
.
>>> import subprocess
>>> cmd = ('date', '-u', '+%A')
>>> p = subprocess.run(cmd, capture_output=True, text=True)
>>> p
CompletedProcess(args=('date', '-u', '+%A'), returncode=0,
stdout='Wednesday\n', stderr='')
>>> p.stdout
'Wednesday\n'
>>> subprocess.check_output(cmd, text=True)
'Wednesday\n'
With check_output()
, you'll get an exception if something goes wrong with the command being executed. With run()
, you'll get that information from stderr
and returncode
as part of the CompletedProcess
object.
>>> cmd = ('ls', 'xyz.txt')
>>> subprocess.run(cmd, capture_output=True, text=True)
CompletedProcess(args=('ls', 'xyz.txt'), returncode=2, stdout='',
stderr="ls: cannot access 'xyz.txt': No such file or directory\n")
>>> subprocess.check_output(cmd, text=True)
ls: cannot access 'xyz.txt': No such file or directory
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/subprocess.py", line 415, in check_output
return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
File "/usr/lib/python3.8/subprocess.py", line 516, in run
raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '('ls', 'xyz.txt')' returned
non-zero exit status 2.
You can also use legacy methods subprocess.getstatusoutput()
and subprocess.getoutput()
but they lack in features and do not provide secure options. See docs.python: subprocess Legacy Shell Invocation Functions for details.
Video demo:
See also my 100 Page Python Intro ebook.