Computer Science Atlas
Snippets

Python 3: Standard Input with subprocess.run()

Part 4 of a Series: subprocess.run()
September 3, 2021
 
Articles in Series: subprocess.run()
  1. Python 3: Execute a System Command Using subprocess.run()
  2. Python 3: Get and Check Exit Status Code (Return Code) from subprocess.run()
  3. Python 3: Get Standard Output and Standard Error from subprocess.run()
  4. Current Article
    Python 3: Standard Input with subprocess.run()
  5. Python 3: Using Shell Syntax with subprocess.run()
  6. Python 3: Specify Environment Variables in subprocess.run()
Table of Contents

Default Behavior: Standard Input Pass-Through

By default, subprocess.run() takes stdin (standard input) from our Python program and passes it through unchanged to the subprocess.

For example, on a Linux or macOS system, the cat - command outputs exactly what it receives from stdin. If we run the following code on a Linux or macOS system:

from subprocess import run

run( [ 'cat', '-' ] )
1
2
3
from subprocess import run

run( [ 'cat', '-' ] )

cat will wait for input from the user. When the user enters input to our Python program's stdin, Python sends that input data to the cat subprocess, which then displays the input on-screen.

Binary Data as Standard Input

If we want to programmatically specify the standard input data for the command we're running, we can use the input= option when calling subprocess.run(). By default, input= accepts bytes, so we can pass binary data bytes directly using the parameter.

The following example loads the binary data contents of myfiles.tar.gz and sends it to the tar command as stdin:

from subprocess import run

with open( 'myfiles.tar.gz', 'rb' ) as f:
    data = f.read()

run( [ 'tar', 'xzf', '-' ], input=data )
1
2
3
4
5
6
from subprocess import run

with open( 'myfiles.tar.gz', 'rb' ) as f:
    data = f.read()

run( [ 'tar', 'xzf', '-' ], input=data )

If a user runs this Python program, the tar xzf - command will extract the contents of myfiles.tar.gz in the user's current directory to the user's current directory.

Since standard input is provided by input=data, the Python program will not wait for the user to input anything.

String as Standard Input

Using .encode()

Since input= expects bytes, if we want to pass in a string, we can first convert the string to bytes using UTF-8 encoding with .encode():

from subprocess import run

message = 'Hello, world!\n'
run( [ 'cat', '-' ], input=message.encode() )
1
2
3
4
from subprocess import run

message = 'Hello, world!\n'
run( [ 'cat', '-' ], input=message.encode() )

Using encoding= option

Alternatively, we could have used the encoding, errors or text parameters along with input and passed in message directly as a string.