Python
subprocess
Popen
stdin
string manipulation

How do I pass a string into subprocess.Popen using the stdin argument?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

To send a string to a child process in Python, create the process with stdin=subprocess.PIPE and then pass the text to communicate(). That pattern is the safest answer because it writes the input, closes standard input, waits for completion, and collects output without leaving the process hanging.

The Standard Popen Pattern

For ordinary text input, enable text mode so Python handles encoding and decoding for you.

python
1import subprocess
2
3proc = subprocess.Popen(
4    ["cat"],
5    stdin=subprocess.PIPE,
6    stdout=subprocess.PIPE,
7    stderr=subprocess.PIPE,
8    text=True,
9)
10
11stdout, stderr = proc.communicate("hello from python\n")
12print(stdout)
13print(proc.returncode)

Here is what matters:

  • 'stdin=subprocess.PIPE gives Python a writable pipe connected to the child's standard input'
  • 'text=True means communicate accepts and returns strings instead of bytes'
  • 'stdout=subprocess.PIPE and stderr=subprocess.PIPE let you inspect the result'

If you only remember one technique, remember this one.

Why communicate() Is Preferred

You can manually write to proc.stdin, but communicate() is usually better because it handles the full request-response lifecycle in one call. It:

  • writes the input data
  • closes stdin so the child sees end-of-input
  • waits for the command to exit
  • reads stdout and stderr safely

That last point matters. Pipes have finite buffers. If you manually write to stdin while the child also produces lots of output, you can deadlock unless you manage both sides carefully.

Sending Bytes Instead Of Text

If the child process expects binary input, do not use text=True. Send bytes directly.

python
1import subprocess
2
3proc = subprocess.Popen(
4    ["python3", "-c", "import sys; sys.stdout.buffer.write(sys.stdin.buffer.read())"],
5    stdin=subprocess.PIPE,
6    stdout=subprocess.PIPE,
7    stderr=subprocess.PIPE,
8)
9
10stdout, stderr = proc.communicate(b"raw bytes\n")
11print(stdout)

In this version, stdout and stderr are also bytes. That is useful when the data is not plain text or when you need exact byte preservation.

A More Realistic Example

Suppose you want to send SQL text or some generated configuration into another command. The mechanism is identical.

python
1import subprocess
2
3payload = "SELECT 1;\nSELECT 2;\n"
4
5proc = subprocess.Popen(
6    ["python3", "-c", "import sys; data = sys.stdin.read(); print(data.upper())"],
7    stdin=subprocess.PIPE,
8    stdout=subprocess.PIPE,
9    stderr=subprocess.PIPE,
10    text=True,
11)
12
13stdout, stderr = proc.communicate(payload)
14print(stdout)

The example child process just uppercases what it reads, but the important part is that your string goes through standard input, not through shell quoting.

Manual Writes Are Possible, But Riskier

You can write to proc.stdin directly if you need a conversational process, but then you must manage the lifecycle yourself.

python
1import subprocess
2
3proc = subprocess.Popen(
4    ["cat"],
5    stdin=subprocess.PIPE,
6    stdout=subprocess.PIPE,
7    text=True,
8)
9
10proc.stdin.write("manual input\n")
11proc.stdin.close()
12stdout = proc.stdout.read()
13proc.wait()
14print(stdout)

This works for simple cases, but it is easier to misuse than communicate(). If the child expects more input, or if stderr fills up and is never read, the process can stall.

Timeouts And Error Handling

When the subprocess might hang, add a timeout.

python
1import subprocess
2
3proc = subprocess.Popen(
4    ["python3", "-c", "import time; time.sleep(5)"],
5    stdin=subprocess.PIPE,
6    stdout=subprocess.PIPE,
7    stderr=subprocess.PIPE,
8    text=True,
9)
10
11try:
12    proc.communicate("ignored\n", timeout=1)
13except subprocess.TimeoutExpired:
14    proc.kill()
15    proc.communicate()
16    print("process timed out")

This is the correct cleanup pattern: kill the process, then call communicate() again to drain any remaining output.

subprocess.run Is Simpler For One-Shot Calls

If you do not need the Popen object itself, subprocess.run is shorter and built around the same idea.

python
1import subprocess
2
3result = subprocess.run(
4    ["cat"],
5    input="hello\n",
6    text=True,
7    capture_output=True,
8    check=True,
9)
10
11print(result.stdout)

Use Popen when you need lower-level control. Use run when you just want to send input once and get the result.

Common Pitfalls

A common mistake is forgetting stdin=subprocess.PIPE. Without that, there is no writable pipe for Python to send the string to.

Another issue is mixing text and bytes incorrectly. If text=True is off, communicate() expects bytes, not Python strings. If text=True is on, send strings and let Python handle encoding.

Developers also sometimes write to proc.stdin manually but never close it. Many programs wait for end-of-input before continuing, so the child appears to hang even though it is behaving correctly.

Finally, do not use shell=True just to pass input data. Standard input is cleaner and avoids shell-quoting bugs.

Summary

  • Use stdin=subprocess.PIPE and communicate() to pass a string into a subprocess safely.
  • Turn on text=True when you want to work with Python strings instead of bytes.
  • Use raw bytes only when the child process expects binary input.
  • Prefer communicate() over manual writes for one-shot interactions.
  • Add timeouts and proper cleanup when the subprocess might block or run too long.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.