Python Tutorial

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

3 min read
Python System Command - os.system(), subprocess.call()
Python System Command - os.system(), subprocess.call()

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.

Stay updated with Netalith

Get coding resources, product updates, and special offers directly in your inbox.