Skip to content

Instantly share code, notes, and snippets.

@timmc-edx
Created January 23, 2026 22:37
Show Gist options
  • Select an option

  • Save timmc-edx/2118ea44c2b8d88dd78b41a4bac5e5b2 to your computer and use it in GitHub Desktop.

Select an option

Save timmc-edx/2118ea44c2b8d88dd78b41a4bac5e5b2 to your computer and use it in GitHub Desktop.
Out-of-order stdout behavior from python buffering
import subprocess
print("=== Start of script")
subprocess.run(['ls', '-ld', '/'], check=True)
print("=== End of script")
# $ python3 test.py
# === Start of script
# drwxr-xr-x 24 root root 4096 Jul 2 2025 /
# === End of script
#
#
# $ python3 test.py | cat
# drwxr-xr-x 24 root root 4096 Jul 2 2025 /
# === Start of script
# === End of script
#
#
# $ PYTHONUNBUFFERED=1 python3 test.py | cat
# === Start of script
# drwxr-xr-x 24 root root 4096 Jul 2 2025 /
# === End of script
@timmc-edx
Copy link
Author

Even happens with print(..., file=sys.stdout) and subprocess.run(..., stdout=sys.stdout).

It turns out that sys.stdout is a wrapper that includes a buffer under some circumstances, but subprocess ganks the file descriptor out of the wrapper and passes that directly to the child process. So subprocess is unbuffered, but print is buffered (sometimes).

@timmc-edx
Copy link
Author

More detail: Python buffering can be disabled, line-based, or full. If stdout is a TTY we get line-based, but otherwise it's full buffering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment