Running a command with run()

subprocess · Essentials · 8 min

Almost every automation script needs to call git, a compiler, ffmpeg or another tool.

subprocess.run(args) starts a program, waits for it to finish, and returns a CompletedProcess object. Pass the command as a list: the program name first, then each argument as its own element.

subprocess.run(["git", "status", "--short"])

Each list element reaches the program exactly as written, with no shell in between, so spaces, quotes and $ in arguments need no escaping. The program is looked up on PATH.

The result has:

  • returncode: 0 means success by convention; anything else means failure.
  • args: what you ran.
  • stdout / stderr: None unless you asked to capture them (next lesson).

By default the child inherits your terminal, so its output appears directly on screen, and run blocks until it exits.

run is the recommended high-level API and covers most needs. Older functions such as call, check_call and check_output still exist and are thin wrappers around it. Avoid os.system in new code: it always goes through the shell and only gives you an encoded exit status.

To run another Python script portably, use sys.executable (the current interpreter) as the program instead of a hardcoded "python".

Example

import subprocess, sys

r = subprocess.run(["echo", "hello", "world with spaces"])
# hello world with spaces
print(r.returncode)          # 0
print(r.args)                # ['echo', 'hello', 'world with spaces']

r = subprocess.run([sys.executable, "-c", "import sys; sys.exit(3)"])
print(r.returncode)          # 3
print(r.stdout)              # None (not captured)

Remember

  • run() starts a program, waits, and returns a CompletedProcess
  • Pass the command as a list of separate arguments
  • returncode 0 means success

Watch out for

  • Passing one string like 'ls -l' without shell=True; on POSIX it looks for a program literally named 'ls -l'.

Check yourself

  1. What does subprocess.run(['ls', '-l', 'my file']) pass to ls?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/subprocess.html#subprocess.run