Skip to content

Instantly share code, notes, and snippets.

@moreati
Created May 15, 2025 11:27
Show Gist options
  • Save moreati/034fef45f73d809d9411a8a63eca34d6 to your computer and use it in GitHub Desktop.
Save moreati/034fef45f73d809d9411a8a63eca34d6 to your computer and use it in GitHub Desktop.
Python subprocesses with closed stdio
import os
import subprocess
import sys
PRINT_STDERR_REPR_PY = 'import sys; print(f" {sys.stderr=}\\n")'
print('Child stderr -> our stderr')
subprocess.run([sys.executable, '-c', PRINT_STDERR_REPR_PY])
print('Child stderr -> /dev/null')
subprocess.run([sys.executable, '-c', PRINT_STDERR_REPR_PY], stderr=subprocess.DEVNULL)
print('Child stderr closed by shell')
subprocess.run(f"{sys.executable} -c '{PRINT_STDERR_REPR_PY}' 2>&-", shell=True)
print('Child stderr -> a closed file object/descriptor')
pid = os.posix_spawn(
sys.executable,
[sys.executable, '-c', PRINT_STDERR_REPR_PY],
os.environ,
file_actions=[(os.POSIX_SPAWN_CLOSE, 2)],
)
_, status = os.waitpid(pid, 0)
assert status == 0
print("Child stderr -> parent's closed sys.stderr object")
subprocess.run([sys.executable, '-c', PRINT_STDERR_REPR_PY])
print("Child stderr -> parent's closed stderr descriptor")
os.close(2)
subprocess.run([sys.executable, '-c', PRINT_STDERR_REPR_PY])
@moreati
Copy link
Author

moreati commented May 15, 2025

Note the cases where sys.stderr == None in the child process

$ python stdio.py
Child stderr -> our stderr
    sys.stderr=<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>

Child stderr -> /dev/null
    sys.stderr=<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>

Child stderr closed by shell
    sys.stderr=None

Child stderr -> a closed file object/descriptor
    sys.stderr=None

Child stderr -> parent's closed sys.stderr object
    sys.stderr=<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>

Child stderr -> parent's closed stderr descriptor
    sys.stderr=None

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