Python System Command - os.system(), subprocess.call()
Step-by-step guide on how to python run shell command using os.system and subprocess (call, check_output, run, Popen), capturing output, exit codes, and security best practices.
Drake Nguyen
Founder · System Architect
Run shell commands from Python
This guide explains how to python run shell command from a script, compare common approaches, and show how to capture output and handle errors. It covers os.system, the subprocess module (call, check_output, Popen, run), and practical tips for safe execution when you need to execute shell commands from python.
When to run shell commands in Python
Sometimes a script needs to invoke external programs—examples include running git to push code, calling date to get system time, or invoking other command-line tools. This article answers how to run shell command in python and how to capture or inspect results programmatically.
os.system()
os.system is a simple way to execute a command. It sends the command output directly to the process standard output and returns the command exit status. Use it only for quick, non-sensitive tasks.
import os
cmd = "git --version"
exit_code = os.system(cmd) # os.system returns the exit status
print("returned value:", exit_code)
Note: output is printed to the console (stdout) rather than returned to your program. This method is less flexible than subprocess-based approaches.
subprocess.call()
subprocess.call executes a command and returns its exit code. Prefer passing the command as a list to avoid invoking a shell. This is a common alternative when you want the exit status but don't need captured output.
import subprocess
# preferred: pass command as a list (avoids shell interpretation)
return_code = subprocess.call(["git", "--version"]) # subprocess.call example python
print("returned value:", return_code)
# if you must use the shell (be careful):
# subprocess.call("git --version", shell=True)
This demonstrates python subprocess call vs os system: both return an exit code, but subprocess.call offers better control and safer defaults.
subprocess.check_output()
Use subprocess.check_output when you need to capture the command output (stdout) as bytes. Decode to a string when required. This answers how to python run terminal command and get output.
import subprocess
output_bytes = subprocess.check_output(["date"]) # returns output as byte string
output = output_bytes.decode("utf-8") # python check_output decode bytes to string
print("Current date is:", output.strip())
If the command exits with a non-zero status, check_output raises subprocess.CalledProcessError so you can catch and handle errors.
subprocess.run and subprocess.Popen
For modern code, subprocess.run (Python 3.5+) is a convenient, flexible API. It can capture stdout/stderr, return a CompletedProcess with attributes, and accept text mode to automatically decode bytes.
import subprocess
result = subprocess.run(["git", "--version"], capture_output=True, text=True)
print(result.stdout.strip())
print("exit code:", result.returncode)
For advanced use cases—streaming output, communicating with stdin, or non-blocking execution—use subprocess.Popen and communicate().
import subprocess
proc = subprocess.Popen(["ls", "-l"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out_bytes, err_bytes = proc.communicate()
print(out_bytes.decode("utf-8"))
print(err_bytes.decode("utf-8"))
print("exit status code:", proc.returncode)
Security and best practices
- Prefer subprocess with a list of arguments instead of shell=True to reduce shell injection risk (shell=True security risk).
- Catch subprocess.CalledProcessError to handle non-zero exit codes when using check_output or run(..., check=True).
- Use text=True or decode bytes to strings for easier string handling (python check_output decode bytes to string).
- Validate or sanitize any data that becomes part of a shell command if you must use shell=True.
- For simple status checks, os.system is quick, but subprocess provides more control for production code.
Quick examples and common questions
- python run git --version in python: use subprocess.run(["git","--version"], capture_output=True, text=True).
- python execute date command with subprocess: subprocess.check_output(["date"]).decode()
- python execute command line and capture output: subprocess.check_output or subprocess.run(..., capture_output=True, text=True).
- python subprocess.Popen run command: use Popen for streaming or interacting with stdin/stdout/stderr.
These techniques let you execute shell utilities, capture stdout/stderr, inspect the exit status, and integrate command-line tools into larger Python workflows. For a deeper dive, consult the official Python subprocess documentation and examples.