The behavior with Popen.communicate() if stdin/stdout/stderr are PIPEs and they are closed before calling communicate() is rather strange.
If both stdout and stderr are PIPEs and one (or both) is closed, communicate() succeeds. If only one of them is a PIPE and it is closed, the behavior changes and there's a ValueError instead:
If stdin is a closed PIPE, the behavior is pretty much the opposite of the above. If other streams are not PIPEs, communicate() succeeds, but if the are other PIPEs, we get a ValueError:
This inconsistency seems to be caused by an optimization that leads to two different code paths depending on the number of PIPEs. I needed to spend some time to understand why our tests behaved seemingly inconsistently after code was refactored.
It would be easy to fix problems by changing code like if self.stdout: to if self.stdout and not self.stdout.closed:. I guess it could be argued that raising a ValueError is the correct way to handle these situations, but in that case it should be raised always.
Tested with Python 3.14 alpha 5. Occurs also with earlier ones.
If this is agreed to be a bug, I can provide a PR fixing these inconsistencies so that closed PIPEs are always handled gracefully. In that case we needed to decide should None or an empty string/bytes (depending on self.text_mode) be returned if stdout or stderr is a closed PIPE. A naïve fix would return None, but the current un-optimized code path returns an empty string/bytes and changing it could cause backwards compatibility problems.
I have a python program that is running Popen.communicate to read the output of a command, and I notice that very often the output is truncated. Is this the issue, which you are describing?
Activity
pekkaklarck commented on Mar 10, 2025
If this is agreed to be a bug, I can provide a PR fixing these inconsistencies so that closed PIPEs are always handled gracefully. In that case we needed to decide should None or an empty string/bytes (depending on self.text_mode) be returned if stdout or stderr is a closed PIPE. A naïve fix would return None, but the current un-optimized code path returns an empty string/bytes and changing it could cause backwards compatibility problems.
aschmitz-crnc commented on Aug 21, 2025
I have a python program that is running Popen.communicate to read the output of a command, and I notice that very often the output is truncated. Is this the issue, which you are describing?
pythongh-131064: Handle closed pipes consistently in communicate
pythongh-131064: Handle closed pipes consistently in communicate
pythongh-131064: Handle closed pipes consistently in communicate