How to suppress or capture the output of subprocess.run()?
Question:
From the examples in docs on subprocess.run()
it seems like there shouldn’t be any output from
subprocess.run(["ls", "-l"]) # doesn't capture output
However, when I try it in a python shell the listing gets printed. I wonder if this is the default behaviour and how to suppress the output of run()
.
Answers:
Here is how to suppress output, in order of decreasing levels of cleanliness. They assume you are on Python 3.
- You can redirect to the special
subprocess.DEVNULL
target.
import subprocess
# To redirect stdout (only):
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL)
# to redirect stderr to /dev/null as well:
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Alternatively, you can merge stderr and stdout streams and redirect
# the one stream to /dev/null
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
- If you want a fully manual method, can redirect to
/dev/null
by opening the file handle yourself. Everything else would be identical to method #1.
import os
import subprocess
with open(os.devnull, 'w') as devnull:
subprocess.run(['ls', '-l'], stdout=devnull)
Here is how to capture output (to use later or parse), in order of decreasing levels of cleanliness. They assume you are on Python 3.
NOTE: The below examples use text=True
.
- This causes the STDOUT and STDERR to be captured as
str
instead of bytes
.
- Omit
text=True
to get bytes
data
text=True
is Python >= 3.7 only, use universal_newlines=True
on Python <= 3.6
universal_newlines=True
is identical to text=True
but more verbose to type but should exist on all Python versions
- If you simply want to capture both STDOUT and STDERR independently, AND you are on Python >= 3.7, use
capture_output=True
.
import subprocess
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)
print(result.stderr)
- You can use
subprocess.PIPE
to capture STDOUT and STDERR independently. This works on any version of Python that supports subprocess.run
.
import subprocess
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, text=True)
print(result.stdout)
# To also capture stderr...
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
print(result.stdout)
print(result.stderr)
# To mix stdout and stderr into a single string
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
print(result.stdout)
ex: to capture the output of ls -a
import subprocess
ls = subprocess.run(['ls', '-a'], capture_output=True, text=True).stdout.strip("n")
print(ls)
From the examples in docs on subprocess.run()
it seems like there shouldn’t be any output from
subprocess.run(["ls", "-l"]) # doesn't capture output
However, when I try it in a python shell the listing gets printed. I wonder if this is the default behaviour and how to suppress the output of run()
.
Here is how to suppress output, in order of decreasing levels of cleanliness. They assume you are on Python 3.
- You can redirect to the special
subprocess.DEVNULL
target.
import subprocess
# To redirect stdout (only):
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL)
# to redirect stderr to /dev/null as well:
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Alternatively, you can merge stderr and stdout streams and redirect
# the one stream to /dev/null
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
- If you want a fully manual method, can redirect to
/dev/null
by opening the file handle yourself. Everything else would be identical to method #1.
import os
import subprocess
with open(os.devnull, 'w') as devnull:
subprocess.run(['ls', '-l'], stdout=devnull)
Here is how to capture output (to use later or parse), in order of decreasing levels of cleanliness. They assume you are on Python 3.
NOTE: The below examples use
text=True
.
- This causes the STDOUT and STDERR to be captured as
str
instead ofbytes
.
- Omit
text=True
to getbytes
datatext=True
is Python >= 3.7 only, useuniversal_newlines=True
on Python <= 3.6
universal_newlines=True
is identical totext=True
but more verbose to type but should exist on all Python versions
- If you simply want to capture both STDOUT and STDERR independently, AND you are on Python >= 3.7, use
capture_output=True
.
import subprocess
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)
print(result.stderr)
- You can use
subprocess.PIPE
to capture STDOUT and STDERR independently. This works on any version of Python that supportssubprocess.run
.
import subprocess
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, text=True)
print(result.stdout)
# To also capture stderr...
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
print(result.stdout)
print(result.stderr)
# To mix stdout and stderr into a single string
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
print(result.stdout)
ex: to capture the output of ls -a
import subprocess
ls = subprocess.run(['ls', '-a'], capture_output=True, text=True).stdout.strip("n")
print(ls)