How to suppress or capture the output of subprocess.run?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Python's subprocess module lets you launch external processes and interact with their input, output, and error streams. The subprocess.run() function, introduced in Python 3.5, is the recommended high-level interface for running shell commands from Python code. A very common need is to either capture the output of a command for further processing or suppress it entirely so it does not clutter the terminal. This article walks you through both techniques with clear, practical examples.
How subprocess.run() Works by Default
When you call subprocess.run() without any output-related arguments, the child process inherits the parent's standard output and standard error streams. That means everything the command prints will appear directly in your terminal.
The returned CompletedProcess object has stdout and stderr attributes, but both are None unless you explicitly ask Python to capture them.
Capturing Output with capture_output
The simplest way to capture both stdout and stderr is to pass capture_output=True. This tells Python to collect the output into the CompletedProcess object instead of sending it to the terminal.
The text=True parameter (also available as universal_newlines=True in older versions) decodes the raw bytes into strings using the system's default encoding. Without it, result.stdout and result.stderr are bytes objects.
Capturing Output with subprocess.PIPE
Under the hood, capture_output=True is shorthand for setting both stdout and stderr to subprocess.PIPE. Using PIPE directly gives you more granular control. For example, you can capture stdout while still letting stderr print to the terminal.
You can also merge stderr into stdout by redirecting it with stderr=subprocess.STDOUT.
Suppressing Output Entirely
Sometimes you do not care about the output at all and just want the command to run silently. The cleanest approach is to redirect both streams to subprocess.DEVNULL, which discards everything.
This is the equivalent of appending > /dev/null 2>&1 to a shell command. The output is never stored in memory, so this is also the most memory-efficient option when dealing with commands that produce large amounts of output.
Checking for Errors While Capturing
When you capture output, you often want to know if the command failed. Pass check=True to make subprocess.run() raise a CalledProcessError if the return code is non-zero.
The exception object carries stdout, stderr, and returncode, so you can inspect exactly what went wrong.
Common Pitfalls
- Forgetting
text=True: Without this flag,stdoutandstderrare rawbytes, which can cause confusingTypeErrorexceptions when you try to concatenate or print them alongside regular strings. - Using
capture_outputwith explicitstdout/stderr: Passingcapture_output=Truetogether withstdout=orstderr=raises aValueErrorbecause the two approaches conflict. - Deadlocks with large output and
PIPE: If you usePopenmanually (instead ofrun) and read only one stream, the other stream's buffer can fill up and block the child process.subprocess.run()handles this for you via internal threading, but it is good to be aware of if you drop down toPopen. - Ignoring
stderr: Capturing onlystdoutmeans error messages still print to the terminal, which can look like your own program's errors to the user. Decide explicitly what to do with stderr. - Shell injection risks: Passing
shell=Truewith unsanitized input opens you up to shell injection attacks. Prefer passing the command as a list of arguments whenever possible.
Summary
- Use
capture_output=True, text=Truefor the simplest way to collect both stdout and stderr as strings. - Use
stdout=subprocess.PIPEorstderr=subprocess.PIPEindividually when you need granular control over which streams to capture. - Use
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULLto silently discard all output. - Combine
stderr=subprocess.STDOUTwithstdout=subprocess.PIPEto merge both streams into a single captured string. - Always consider adding
check=Trueso failures are raised as exceptions rather than silently ignored.
Related reading
- How to suppress Pandas Future warning?
- How to suppress py.test internal deprecation warnings
- How to suppress scientific notation when printing float values?
- How to suppress specific warning in Tensorflow Python
- How to Suppress Tensorflow warning displayed in result
- How to switch position of two items in a Python list?
- How to take column-slices of dataframe in pandas
- How to take the first N items from a generator or list?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.