Question
How can I run an external program or system command from Python, similar to typing the command directly into a shell or command prompt?
For example, I want to launch a command-line program from Python code, optionally pass arguments to it, and possibly capture its output or check whether it succeeded.
Short Answer
By the end of this page, you will understand how Python runs external commands, when to use the subprocess module, how to pass arguments safely, how to capture output, and how to avoid common mistakes such as shell injection or incorrect argument formatting.
Concept
Running a system command from Python means starting another program from your Python script.
In Python, the standard and recommended way to do this is with the subprocess module. It lets your code:
- start another program
- pass command-line arguments
- wait for it to finish
- read its output
- check its exit status
This matters because real programs often need to interact with other tools. For example:
- a Python script may call
git - a deployment script may run
dockerornpm - a data pipeline may execute a compression tool
- a utility script may open another application
The key idea is that Python is not "typing into a terminal" the way a human does. Instead, it asks the operating system to start another process.
The modern recommendation is:
- use
subprocess.run()for most simple cases - use
subprocess.Popen()for more control - avoid older approaches like
os.system()unless you specifically need its limited behavior
One of the most important parts of this topic is safety. If you build command strings from user input and pass them through a shell, you can accidentally create serious security problems. That is why Python usually works best when you pass the command and its arguments as a list.
Mental Model
Think of your Python script as a manager in an office.
- Python is the manager.
- An external command is another worker.
subprocess.run()is the manager giving that worker a task.- The argument list is the instruction sheet.
- The return code is the worker reporting success or failure.
- Captured output is the written report the worker brings back.
If you send the instructions clearly as separate pieces, the task is usually done correctly. If you send one big messy string through a shell, the shell has to interpret it first, which adds complexity and risk.
Syntax and Examples
Basic syntax
The most common way to run a command is:
import subprocess
subprocess.run(["command", "arg1", "arg2"])
This starts the program and waits for it to finish.
Example: run a simple command
import subprocess
subprocess.run(["echo", "Hello from Python"])
This runs the echo command with one argument.
Capture output
import subprocess
result = subprocess.run(
["echo", "Hello"],
capture_output=True,
text=True
)
print(result.stdout)
print(result.returncode)
What this does
capture_output=Truecollects standard output and standard errortext=Truereturns strings instead of bytesresult.stdoutcontains normal outputresult.stderrcontains error output
Step by Step Execution
Consider this example:
import subprocess
result = subprocess.run(
["echo", "Python subprocess"],
capture_output=True,
text=True
)
print("Return code:", result.returncode)
print("Output:", result.stdout)
Here is what happens step by step:
- Python imports the
subprocessmodule. subprocess.run()is called.- Python asks the operating system to start the
echoprogram. - The program receives one argument:
Python subprocess. - Because
capture_output=True, the program's output is saved instead of printed directly to the terminal. - Because
text=True, the saved output is decoded into a normal Python string. - The command finishes.
- Python stores the result in
result. result.returncodeis printed. For a successful command, this is usually0.result.stdoutis printed, which contains the command output.
A typical output might be:
Real World Use Cases
Running external commands is common in practical Python work.
Automation scripts
A script may:
- create folders
- copy files
- compress logs
- run backup tools
Development tools
Python can call tools such as:
gitto inspect repositoriespytestto run testsnpmto build frontend assetsdockerto start containers
Data processing
A Python program may use existing command-line tools for:
- image conversion
- video encoding
- file decompression
- database export/import
System administration
Admins often use Python to:
- restart services
- inspect processes
- query system information
- schedule maintenance tasks
Integration with legacy tools
Sometimes a company already has reliable command-line programs. Python can act as the glue code that calls them and processes their results.
Real Codebase Usage
In real projects, developers usually wrap command execution in small helper functions instead of scattering subprocess.run() everywhere.
Common patterns
Guard clauses
Check that needed values exist before running the command.
import subprocess
def show_file(path):
if not path:
raise ValueError("path is required")
return subprocess.run(["cat", path], capture_output=True, text=True, check=True)
Early failure with check=True
This makes scripts fail immediately when an important command does not succeed.
subprocess.run(["git", "status"], check=True)
Validation before execution
If arguments come from configuration or users, validate them first.
allowed_envs = {"dev", "staging", "prod"}
env = "dev"
env allowed_envs:
ValueError()
Common Mistakes
1. Using one command string when a list is safer
Broken approach:
import subprocess
filename = "my file.txt"
subprocess.run("cat " + filename, shell=True)
Problems:
- spaces can break the command
- shell metacharacters may be interpreted
- user input can become dangerous
Better approach:
import subprocess
filename = "my file.txt"
subprocess.run(["cat", filename])
2. Forgetting that shell built-ins are different
Some commands are not standalone programs. For example, dir on Windows is usually handled by cmd.
import subprocess
subprocess.run(["dir"])
This may fail because dir is not an executable program.
Use:
subprocess.run(["cmd", "/c", "dir"])
3. Not capturing output when you need it
Comparisons
| Approach | Recommended? | Best for | Notes |
|---|---|---|---|
subprocess.run([...]) | Yes | Most command execution tasks | Safe and simple when using a list of arguments |
subprocess.run("...", shell=True) | Sometimes | Shell features like pipes, redirects, built-ins | More flexible, but riskier |
subprocess.Popen(...) | Yes, when needed | Advanced process control | Useful for streaming, background processes, and manual I/O |
os.system("...") | Usually no | Very simple legacy code | Limited control and harder to work with safely |
subprocess.run() vs
Cheat Sheet
import subprocess
Run a command
subprocess.run(["command", "arg1", "arg2"])
Capture output as text
result = subprocess.run(
["command", "arg1"],
capture_output=True,
text=True
)
print(result.stdout)
print(result.stderr)
print(result.returncode)
Raise an error if the command fails
subprocess.run(["command"], check=True)
Run in a specific directory
subprocess.run(["command"], cwd="/path/to/folder")
Use custom environment variables
import os
env = os.environ.copy()
env["DEBUG"] = "1"
subprocess.run(["command"], env=env)
When to use
FAQ
How do I run a terminal command in Python?
Use subprocess.run():
import subprocess
subprocess.run(["echo", "hello"])
What is the best way to execute a shell command in Python?
Usually, subprocess.run() with a list of arguments is the best choice because it is safer and easier to control.
How do I capture command output in Python?
Use capture_output=True and text=True:
result = subprocess.run(["echo", "hello"], capture_output=True, text=True)
print(result.stdout)
What does shell=True do in Python?
It runs the command through the system shell. This allows shell features, but it can introduce security and quoting problems.
How do I know whether a command succeeded?
Check result.returncode, or use check=True to raise an exception automatically on failure.
Why does my command work in the terminal but not in Python?
Mini Project
Description
Build a small Python utility that runs a system command entered in code, captures the output, and reports whether the command succeeded. This demonstrates the most common real-world use of subprocess.run(): executing a command safely and reading the result inside Python.
Goal
Create a Python script that runs an external command, prints its output, prints any error output, and shows the exit code.
Requirements
- Use Python's
subprocessmodule - Run a command by passing the program and arguments as a list
- Capture both standard output and standard error
- Print the exit code after the command finishes
- Handle command failure without crashing unexpectedly
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Catch Multiple Exceptions in One except Block in Python
Learn how to catch multiple exceptions in one Python except block using tuples, with examples, mistakes, and real-world usage.
Convert Bytes to String in Python 3
Learn how to convert bytes to str in Python 3 using decode(), text mode, and proper encodings with practical examples.