Skip to content
shellhacks.dev
Python

Pass stdin to a Command in Python with subprocess.run

Send text to a command's standard input with subprocess.run(input=...). A str needs text=True, bytes need none, and input cannot be combined with stdin.

1 min read
Summarize in AI

You want to feed data to a program such as sort without writing a temporary file.

Python
import subprocess

r = subprocess.run(["sort"], input="pear\napple\nfig\n", capture_output=True, text=True)
print(r.stdout, end="")

r = subprocess.run(["wc", "-c"], input=b"\x00\x01\x02", capture_output=True)
print(r.stdout.decode().strip())

try:
    subprocess.run(["sort"], input=b"bytes", text=True)
except TypeError as e:
    print("TypeError:", e)

try:
    subprocess.run(["sort"], input="x", stdin=subprocess.DEVNULL)
except ValueError as e:
    print("ValueError:", e)
Text
apple
fig
pear
3
TypeError: write() argument must be str, not bytes
ValueError: stdin and input arguments may not both be used.

The input argument is written to the child's standard input and then closed. With text=True it must be a str, as in the first call that sorted three words. Without it, input must be bytes, and wc -c counted three bytes. Mixing them up produces TypeError: write() argument must be str, not bytes, and passing both input and stdin raises ValueError. See subprocess.run.

input is sent in one piece and the call blocks until the child exits, so it suits modest amounts of data. To stream a large input while reading output, use Popen and communicate, or threads. A child that does not read its input, such as true, may fail with a broken pipe.

Share

More snippets

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.