os.system
The old one-liners for running a shell command. os.system (Unix, Windows) cannot capture output and returns a platform-dependent status; os.popen (Unix, Windows) is a thin wrapper around subprocess.Popen with shell=True; os.startfile is Windows only. New code should use subprocess.run.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| command | str | yes | system(): the command line, run by the shell (/bin/sh on Unix, COMSPEC - usually cmd.exe - on Windows). |
| cmd | str | yes | popen(): the command line, also run through the shell. |
| mode | str | no ('r') | popen(): 'r' to read the command's stdout, 'w' to write to its stdin. Anything else raises ValueError. |
| buffering | int | no (-1) | popen(): same meaning as for open(); 0 (unbuffered) is rejected with ValueError. |
| path | str | PathLike | yes | startfile(): the file or folder to open with its associated application (Windows only). |
| operation | str | no | startfile(): a shell verb such as 'open', 'print', 'edit', 'explore' or 'find'. |
Return value
int | file object | None — system(): an exit status (wait status on Unix, exit code on Windows). popen(): a text file object connected to the command. startfile(): None, it returns as soon as the application is launched.
Common patterns
import subprocess result = subprocess.run(['git', 'rev-parse', 'HEAD'], capture_output=True, text=True, check=True) commit = result.stdout.strip()
import os with os.popen('ls -l') as p: listing = p.read()
import os status = os.system('make build') code = status if os.name == 'nt' else os.waitstatus_to_exitcode(status)
import os, subprocess, sys if sys.platform == 'win32': os.startfile('report.pdf') elif sys.platform == 'darwin': subprocess.run(['open', 'report.pdf']) else: subprocess.run(['xdg-open', 'report.pdf'])
Examples
Pitfalls
import os, sys p = os.popen(f'"{sys.executable}" -c "print(1)"') p.read() p.close() == 0
import os, sys p = os.popen(f'"{sys.executable}" -c "print(1)"') p.read() p.close() is None
name = 'report.txt; echo hacked' f'cat {name}'
import subprocess, sys name = 'report.txt; echo hacked' r = subprocess.run([sys.executable, '-c', 'import sys; print(sys.argv[1:])', name], capture_output=True, text=True) r.stdout
When to use
- Quick scripts where a shell one-liner is the point (pipes, globbing) and the input is trusted
- os.startfile: opening a document or folder the way a double click in Explorer would (Windows)
- Capturing output, checking errors, timeouts → subprocess.run(..., capture_output=True, text=True, check=True)
- Anything containing user input → subprocess.run with a list of arguments, no shell
- Long-running or interactive children → subprocess.Popen
Notes
FAQ
os.system and os.popen exist on Unix and Windows (not WASI, Android or iOS), and os.startfile is Windows only. os.system lets the command write straight to the console, bypassing Python, so its output cannot be shown or captured; the examples use os.popen and subprocess with a Python child process instead, which behave the same on every OS.