Retrieving the output of subprocess.call
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
subprocess.call() does not return a command's stdout. It only runs the process, waits for it to finish, and returns the exit code. If you need the actual output, use subprocess.run() with output capture, subprocess.check_output(), or Popen for streaming control.
What subprocess.call() Actually Returns
The most common misunderstanding is treating subprocess.call() as if it returns the text printed by the child process.
The child prints hello to the terminal, but the Python variable receives only the process return code. That is by design.
So if your question is "how do I retrieve the output," the first answer is: call() is the wrong API for that job.
Use subprocess.run() in Modern Python
For current Python code, subprocess.run() is usually the best default. It can capture both stdout and stderr.
This is the modern, readable replacement for many older call() and Popen() use cases.
If you want the command to raise on failure:
Then a non-zero exit status becomes a CalledProcessError.
Use check_output() for Stdout Only
If you only care about stdout and want a small API surface, subprocess.check_output() is still useful.
This is concise, but it is less flexible than run() because the return value is just the captured stdout.
For new code, run() is often the clearer choice.
Capture Both Stdout and Stderr
Sometimes the real diagnostic information is on stderr, not stdout.
This separation is helpful for:
- command wrappers
- CI tooling
- debugging build failures
- scripts that need clean machine-readable stdout
If you deliberately want stderr merged into stdout, redirect it:
Use Popen for Streaming or Interactive Cases
run() is great when you can wait for the whole command to finish. Use Popen when you need more control.
That pattern is useful for long-running commands, interactive tools, or streaming output line by line.
Prefer Argument Lists Over shell=True
Most subprocess code should pass a list of arguments rather than a shell string.
This is safer and avoids quoting problems. shell=True is only appropriate when you intentionally need shell syntax such as pipes, wildcards, or built-in shell commands.
If you do use shell=True, treat untrusted input as dangerous.
Common Pitfalls
- Expecting
subprocess.call()to return stdout instead of the exit code. - Using old APIs when
subprocess.run()would be simpler. - Forgetting
text=Trueand then wondering why output is bytes. - Ignoring stderr and debugging the wrong stream.
- Using
shell=Truewhen a normal argument list would be safer.
Summary
- '
subprocess.call()returns only the process exit code.' - Use
subprocess.run()withcapture_output=Truefor most output-capture cases. - Use
check_output()when you only need stdout. - Use
Popenwhen you need streaming or finer control. - Prefer argument lists over
shell=Trueunless shell features are truly required.
Related reading
- Retry Lost or Failed Tasks (Celery, Django and RabbitMQ)
- Return a default value if a dictionary key is not available
- return coefficients from Pipeline object in sklearn
- Return first N keyvalue pairs from dict
- Retrofit 2.0 how to get deserialised error response.body
- Retrying a failed async/promise function?
- Return HTTP status code 201 in flask
- Return JSON response from Flask view
.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.