Learn subprocess

Run external programs from Python and talk to their input and output

13 lessons · 2 hours · 4 levels · covers subprocess Python 3.13

subprocess is the standard way to start other programs from Python, pass them arguments and input, capture their output and react to their exit status. It replaces os.system and shell scripts in build tools, deployment scripts, test harnesses and automation. Learning it well means scripts that are safe from shell injection, never hang, and fail loudly.

Before you start

subprocess builds on these; the tree links to the exact lessons you need.

How deep do you want to go?

1. EssentialsRead and write simple code, do the everyday basics4 lessons · 35 min in total
2. PracticalUse it productively at work, with the usual idioms7 lessons · 1 hour in total
3. AdvancedThe less common features, performance and trade-offs10 lessons · 2 hours in total
4. ExpertInternals and the edge cases experts know13 lessons · 2 hours in total

The subprocess tree

subprocessRunning a command with run()Running a commandwith run()Capturing outputCapturing outputFailing loudly with check=TrueFailing loudly withcheck=Trueshell=True and safe quotingshell=True and safequotingSending input and chaining commandsSending input andchaining commandsTimeoutsTimeoutsEnvironment, working directory and PATHEnvironment,working directory a…ListsListsDefining functionsDefining functionsErrors and try/exceptErrors and try/exceptStrings and f-stringsStrings and f-strings
Essentials and Practical shown (7 of 13 lessons); the full list is below. Click a lesson to read it.

All 13 lessons, in order

Running commands

  1. Running a command with run() · Essentials · 8 min

    Start a program with subprocess.run, passing the command as a list of arguments, and read its exit code.

  2. Capturing output · Essentials · 8 min

    Capture a command's stdout and stderr as text with capture_output=True and text=True.

  3. Failing loudly with check=True · Essentials · 9 min

    Turn non-zero exit codes into exceptions with check=True and handle CalledProcessError and FileNotFoundError.

  4. shell=True and safe quoting · Essentials · 10 min

    Know what shell=True does, why it enables command injection, and how shlex.quote and shlex.split help.

Input, output and environment

  1. Sending input and chaining commands · Practical · 9 min

    Feed data to a command with input=, avoid accidental terminal reads, and chain programs without a shell.

  2. Timeouts · Practical · 8 min

    Stop commands that run too long with timeout= and handle subprocess.TimeoutExpired.

  3. Environment, working directory and PATH · Practical · 9 min

    Control where a command runs and what environment it sees with cwd=, env= and shutil.which.

Popen and long-running processes

  1. Popen: streaming output · Advanced · 12 min

    Use subprocess.Popen to start a process without waiting and read its output line by line as it runs.

  2. Pipes, communicate() and deadlocks · Advanced · 12 min

    Avoid pipe-buffer deadlocks with communicate(), and connect Popen processes into real pipelines.

  3. Stopping processes and exit statuses · Advanced · 10 min

    Stop processes gracefully with terminate() then kill(), and interpret negative return codes.

Processes at the OS level

  1. Process groups and killing trees · Expert · 13 min

    Run children in their own session or process group so you can signal or kill a whole process tree.

  2. File descriptors and secure spawning · Expert · 12 min

    Control which file descriptors children inherit and drop privileges with close_fds, pass_fds, user and umask.

  3. How processes are spawned · Expert · 12 min

    See how subprocess creates processes: fork/exec, vfork and posix_spawn on POSIX, CreateProcess on Windows.