.communicate() writes input (there is no input in this case so it just closes subprocess' stdin to indicate to the subprocess that there is no more input), reads all output, and waits for the subprocess to exit.

The exception EOFError is raised in the child process by raw_input() (it expected data but got EOF (no data)).

p.stdout.read() hangs forever because it tries to read all output from the child at the same time as the child waits for input (raw_input()) that causes a deadlock.

To avoid the deadlock you need to read/write asynchronously (e.g., by using threads or select) or to know exactly when and how much to read/write, for example:

from subprocess import PIPE, Popen

p = Popen(["python", "-u", "1st.py"], stdin=PIPE, stdout=PIPE, bufsize=1)
print p.stdout.readline(), # read the first line
for i in range(10): # repeat several times to show that it works
    print >>p.stdin, i # write input
    p.stdin.flush() # not necessary in this case
    print p.stdout.readline(), # read output

print p.communicate("n\n")[0], # signal the child to exit,
                               # read the rest of the output, 
                               # wait for the child to exit

Note: it is a very fragile code if read/write are not in sync; it deadlocks.

Beware of block-buffering issue (here it is solved by using "-u" flag that turns off buffering for stdin, stdout in the child).

bufsize=1 makes the pipes line-buffered on the parent side.

Answer from jfs on Stack Overflow
🌐
Python
docs.python.org › 3 › library › subprocess.html
subprocess — Subprocess management
6 days ago - The input argument is passed to Popen.communicate() and thus to the subprocess’s stdin. If used it must be a byte sequence, or a string if encoding or errors is specified or text is true.
Top answer
1 of 3
80

.communicate() writes input (there is no input in this case so it just closes subprocess' stdin to indicate to the subprocess that there is no more input), reads all output, and waits for the subprocess to exit.

The exception EOFError is raised in the child process by raw_input() (it expected data but got EOF (no data)).

p.stdout.read() hangs forever because it tries to read all output from the child at the same time as the child waits for input (raw_input()) that causes a deadlock.

To avoid the deadlock you need to read/write asynchronously (e.g., by using threads or select) or to know exactly when and how much to read/write, for example:

from subprocess import PIPE, Popen

p = Popen(["python", "-u", "1st.py"], stdin=PIPE, stdout=PIPE, bufsize=1)
print p.stdout.readline(), # read the first line
for i in range(10): # repeat several times to show that it works
    print >>p.stdin, i # write input
    p.stdin.flush() # not necessary in this case
    print p.stdout.readline(), # read output

print p.communicate("n\n")[0], # signal the child to exit,
                               # read the rest of the output, 
                               # wait for the child to exit

Note: it is a very fragile code if read/write are not in sync; it deadlocks.

Beware of block-buffering issue (here it is solved by using "-u" flag that turns off buffering for stdin, stdout in the child).

bufsize=1 makes the pipes line-buffered on the parent side.

2 of 3
29

Do not use communicate(input=""). It writes input to the process, closes its stdin and then reads all output.

Do it like this:

p=subprocess.Popen(["python","1st.py"],stdin=PIPE,stdout=PIPE)

# get output from process "Something to print"
one_line_output = p.stdout.readline()

# write 'a line\n' to the process
p.stdin.write('a line\n')

# get output from process "not time to break"
one_line_output = p.stdout.readline() 

# write "n\n" to that process for if r=='n':
p.stdin.write('n\n') 

# read the last output from the process  "Exiting"
one_line_output = p.stdout.readline()

What you would do to remove the error:

all_the_process_will_tell_you = p.communicate('all you will ever say to this process\nn\n')[0]

But since communicate closes the stdout and stdin and stderr, you can not read or write after you called communicate.

Discussions

Please help me understand how subprocess.popen works
Hello Python Masters…I am a beginner…Please help me understand how this code works: PyLocScript = r"C:\Phyton\PyApps\CSV_values_analyze.py" CsvLink = r"C:\Phyton\PyApps\sample.csv" PartNo = "LM3339" area = 45 xcor = 1.5… More on discuss.python.org
🌐 discuss.python.org
3
0
November 4, 2022
Usage of python's subprocess.Popen.communicate() - Ansible Developer - Ansible
Hi, I wasn’t sure whether to report this as a bug or not. The issue was this: I have an rsync task that I use for efficiently copying directory hierarchies to remote machines. The symptom is that it would sometimes hang during the rsync task. ps would reveal that the rsync process was done, ... More on forum.ansible.com
🌐 forum.ansible.com
0
January 15, 2014
How to get output from subprocess.Popen along with visible execution?
I am trying to get the output by ... is test2.py import subprocess cmd = "python3 test.py" process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=true, text=true) output, error = process.communicate() print(output, error) Now usually the execution ... More on discuss.python.org
🌐 discuss.python.org
6
1
July 22, 2024
Popen's communicate vs stdin.write: Why warning? What instead?
When in doubt, there's always source code. https://github.com/python/cpython/blob/main/Lib/subprocess.py#L1165 Looks like a lot of care went into making it more user-friendly. For example, it writes to stdin using separate daemon thread, so if you decide to interrupt it or your subprocess hangs, it won't deadlock python code More on reddit.com
🌐 r/learnpython
4
1
October 20, 2023
🌐
Ansible
forum.ansible.com › archives › ansible developer
Usage of python's subprocess.Popen.communicate() - Ansible Developer - Ansible
January 15, 2014 - Hi, I wasn’t sure whether to report this as a bug or not. The issue was this: I have an rsync task that I use for efficiently copying directory hierarchies to remote machines. The symptom is that it would sometimes hang during the rsync task. ps would reveal that the rsync process was done, but being held onto by the parent process (defunct).
🌐
DataCamp
datacamp.com › tutorial › python-subprocess
An Introduction to Python Subprocess: Basics and Examples | DataCamp
September 12, 2025 - The stdout of the ls command is connected to the stdin of the grep command using subprocess.PIPE, which creates a pipe between the two processes. The communicate() method is used to send the output of the ls command to the grep command and retrieve the filtered output.
Find elsewhere
🌐
Python
bugs.python.org › issue41406
Issue 41406: subprocess: Calling Popen.communicate() after ...
July 27, 2020 - This issue tracker has been migrated to GitHub, and is currently read-only. For more information, see the GitHub FAQs in the Python's Developer Guide · This issue has been migrated to GitHub: https://github.com/python/cpython/issues/85578
🌐
Reddit
reddit.com › r/learnpython › popen's communicate vs stdin.write: why warning? what instead?
r/learnpython on Reddit: Popen's communicate vs stdin.write: Why warning? What instead?
October 20, 2023 -

The Popen docs warn against using Popen.stdin (etc), saying:

Warning: Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.

Is there further explanation somewhere? What does this warning mean practically, for the use of process.stdin.write and .flush in the example code below? Is there another way to send input to a running process, which doesn't assume the process will exit after receiving input?

For context, I've got several examples of executables that accept input on stdin continually, processing lines as they come in. I'd like to run one, send input to the process, and do other things in python before sending more input. The recommended Popen.communicate doesn't support this requirement, since it waits for the process to close after sending input. I haven't found any way to do it.

The following trimmed-down example code works with cat; the real example executables have more significant processing of their input.

import subprocess
import time

duration=1
items=[
    'spam',
    'spam & spam',
    'spam, spam, spam, eggs & spam'
    ]

with open( 'outfile', 'a' ) as outfile:
    with subprocess.Popen(
            [ 'cat' ],
            stdin=subprocess.PIPE,
            stdout=outfile,
            stderr=subprocess.DEVNULL
            ) as process:
        for item in items:
            process.stdin.write(\
                    ('order "' + item + '"\n')\
                    .encode( 'utf-8' ) )
            process.stdin.flush()
            time.sleep( duration )

(edit: this code actually works with the example executables, so I'm wondering when / if the deadlocks will actually affect me)

🌐
Reddit
reddit.com › r/learnpython › am i safe to use subprocess.popen.communicate with pipes and large output?
r/learnpython on Reddit: Am I safe to use subprocess.Popen.communicate with pipes and large output?
May 15, 2018 -

There seems to be tons of conflicting information on the web about whether it is safe to use subprocess.Popen and communicate when using subprocess.PIPE. Some sites say a large output will deadlock while others say that just using communicate will be sufficient.

Can someone give me the final word? Is communicate safe enough even for really big outputs?

I tested it locally with about 10mb of output and it is fine but with this kind of thing, I am never sure if it is a local thing.

I do not need to read from the output until it is finished (otherwise, I would have to use something besides communicate)

Thanks!

🌐
Medium
medium.com › more-python › concurrency-in-python-part-vii-the-subprocess-module-bb54e4134eaa
Concurrency in Python, Part VII — The subprocess Module | by Mikhail Berkov | More Python | Medium
February 9, 2025 - To send input, we simply pass it as an argument to communicate: import subprocess process = subprocess.Popen(["cat"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True) output, _ = process.communicate("Hello, Popen!") print(output) # ...
🌐
Python Module of the Week
pymotw.com › 2 › subprocess
subprocess – Work with additional processes - Python Module of the Week
In the second example, the same 10 numbers are written but the output is read all at once using communicate(). import subprocess print 'One line at a time:' proc = subprocess.Popen('python repeater.py', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) for i in range(10): proc.stdin.write('%d\n' % i) output = proc.stdout.readline() print output.rstrip() remainder = proc.communicate()[0] print remainder print print 'All output at once:' proc = subprocess.Popen('python repeater.py', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, ) for i in range(10): proc.stdin.write('%d\n' % i) output = proc.communicate()[0] print output
🌐
GitHub
gist.github.com › waylan › 2353749
Writing to a python subprocess pipe · GitHub
There's no call to p.wait() (which communicate does by default) so anything after the loop runs before the subproccess (less in this case) is closed. Adding a call to wait after the loop causes even weirder behavior. from subprocess import Popen, PIPE out = [] p = Popen('less', stdin=PIPE) for x in xrange(100): out.append('Line number %d.' % x) p.communicate('\n'.join(out))
🌐
DaniWeb
daniweb.com › programming › software-development › threads › 261056 › communicate-using-subprocess
python - Communicate using subprocess [SOLVED] | DaniWeb
February 17, 2010 - Popen.communicate() both sends any input you give it and then waits for the process to finish, so it is fine for one-shot inputs (like answering a single yes/no) but it closes the stdin it writes to before returning.
🌐
Python
docs.python.org › 3 › library › asyncio-subprocess.html
Subprocesses — Python 3.14.3 documentation
February 23, 2026 - See also the Subprocess and Threads section. ... Wait for the child process to terminate. Set and return the returncode attribute. ... This method can deadlock when using stdout=PIPE or stderr=PIPE and the child process generates so much output that it blocks waiting for the OS pipe buffer to accept more data. Use the communicate() method when using pipes to avoid this condition.
🌐
Reddit
reddit.com › r/learnpython › subprocess.popen and output
r/learnpython on Reddit: subprocess.Popen and output
December 7, 2022 -

I'm trying to grok subprocess.Popen to run and monitor a command line executable in the background. (Specifically, the HandbrakeCLI video converter.)

In this I have been partially successful, using the following command:

handbrake = subprocess.Popen( cmd )

Where cmd is a list of parameters. When I do this, I can do other things while it's running, poll() it, and terminate it if desired, and unless I kill it, it runs to completion exactly the way I want. The problem is that I also want to suppress the output. No problem, right?

handbrake = subprocess.Popen( cmd, stdout=subprocess.PIPE )

This works, but there's still SOME output. Now, my first thought was that the messages I was seeing were techincally ERROR messages. So I tried two different methods:

handbrake = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
handbrake = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )

In both cases, the subprocess launches, I can do other things, but... it doesn't do anything. I can see HandbrakeCLI in the task manager, but it's not using any resources (where it *should* be using nearly 100%), and no file has been created in the target directory.

This leaves me with two questions that may or may not be related:

  1. Why is redirecting stdout causing the program to do nothing?

  2. Where is that other output coming from, and how do I suppress it? (Helpfully, it doesn't contain any information I need to capture.)

🌐
Real Python
realpython.com › python-subprocess
The subprocess Module: Wrapping Programs With Python – Real Python
January 18, 2025 - By using subprocess, you can execute shell commands like ls or dir, launch applications, and handle both input and output streams. This module provides tools for error handling and process communication, making it a flexible choice for integrating ...
🌐
Reddit
reddit.com › r/learnpython › sending asynchronous input to a constantly-running "subprocess"
r/learnpython on Reddit: Sending asynchronous input to a constantly-running "subprocess"
September 22, 2023 -

Hi everyone,

I am trying to use subprocess.Popen to open Powershell, and from this instance, open a secondary application (such that I can send it asynchronous Powershell commands from my Python code).

However, the subprocess.communicate() method seems to permanently close the stdin/stdout stream of the subprocess, which prevents me from sending it subsequent commands:

class _CLI:
def __init__(cls, appExe, appArgs, cmdlet, shell=True):
    cls._interface = subprocess.Popen(f"{appExe} {appArgs}", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell)

def _execute(cls, cmd)
    # ONLY WORKS ONCE
    cls._interface.stdin.write(f"{cmd}\n".encode(encoding))
    output, error = self._interface.communicate()
    return output, error
# ...

max = _CLI(appExe="powershell.exe", cmd="3dsMax", shell=True)
max._execute("SOMETHING COOL")

When I create a new subprocess for each command, that seems to work, but I specifically don't want to open a new application each time I run a command:

class _CLI:
def init(cls, appExe, appArgs, cmdlet, shell=True):
    cls._interface = None
    cls.appExe = appExe
    cls.appArgs = appArgs

def _execute(cls, cmd)
    # WORKS FOR SUBSEQUENT CALLS
    cls._interface = subprocess.Popen(f"{cls.appExe} {cls.appArgs}", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell) cls._interface.stdin.write(f"{cmd}\n".encode(encoding)) 
    output, error = self._interface.communicate()
    return output, error
#...

max = _CLI(appExe="powershell.exe", cmd="3dsMax", shell=True)
max._execute("SOMETHING COOL")

It seems that the status of stdin/stdout is a protected property, and subprocess doesn't have any accessible methods to re-open it. I noticed that subprocess.execute() has a timeout parameter, and I figured that maybe it was just waiting for an unspecified timeout (and hanging indefinitely since it wasn't set). However, adjusting that value didn't seem to do anything.

If anyone has any suggestions, I'd really appreciate it!

EDIT: fixed the busted formatting

Top answer
1 of 2
3
As an aside, you might find pexpect (or wexpect on Windows) more effective for this. https://pexpect.readthedocs.io/en/stable/
2 of 2
2
It's still a mystery to me why subprocess has a multitude of near identical functions that block until the process has finished completely. You cannot use communicate. You cannot use many of the other functions either. But you already use stdin.write which is your primary method of communication. If you want to give more commands you would just stdin.write again. In contrast to threading, Popen creates AND starts/runs a process. If you remove the communicate the process will still start up and receive and process your stdin just fine. (Maybe flushing could help if nothing is received.) If you want to send further instructions you can write them into stdin again. Whether the subprocess knows what to do with your stdin is another matter altogether. If your process has no GUI (just a console) and don't need the program to process stdout/stderr you could also remove the pipes on stdout and stderr which will print their messages directly into the console. If your program does need stdout/stderr you can .read though it takes some care to avoid blocking. Also, are you sure you need shell=True? This inserts a cmd.exe between Python and the command to start powershell.exe which should already be able to find things like 3dsMax. (And if you do start Python from a console anyway then the chain of commands is like cmd->python->cmd->powershell->3dsMax.) And the recommended first argument for Popen is a list. Use [cls.appExe, cls.appArgs].