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 to subprocess.run()
  • subprocess.check_output() if you only want stdout

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.

info 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:


info See also my 100 Page Python Intro ebook.