python / cpython

The Python programming language
https://www.python.org/
Other
61.27k stars 29.55k forks source link

AttributeError in Popen.communicate() #74389

Open 234a2386-3440-4ad4-a9a9-2b5f29559ce9 opened 7 years ago

234a2386-3440-4ad4-a9a9-2b5f29559ce9 commented 7 years ago
BPO 30203

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields: ```python assignee = None closed_at = None created_at = labels = ['type-bug'] title = 'AttributeError in Popen.communicate()' updated_at = user = 'https://bugs.python.org/LukeCampagnola' ``` bugs.python.org fields: ```python activity = actor = 'Luke Campagnola' assignee = 'none' closed = False closed_date = None closer = None components = [] creation = creator = 'Luke Campagnola' dependencies = [] files = [] hgrepos = [] issue_num = 30203 keywords = [] message_count = 2.0 messages = ['292575', '292577'] nosy_count = 1.0 nosy_names = ['Luke Campagnola'] pr_nums = [] priority = 'normal' resolution = None stage = None status = 'open' superseder = None type = 'behavior' url = 'https://bugs.python.org/issue30203' versions = ['Python 3.5'] ```

234a2386-3440-4ad4-a9a9-2b5f29559ce9 commented 7 years ago

In my application, calling communicate() on a Popen instance is giving the following exception:

. . . File "/usr/lib/python3.5/subprocess.py", line 1072, in communicate stdout, stderr = self._communicate(input, endtime, timeout) File "/usr/lib/python3.5/subprocess.py", line 1693, in _communicate stdout = self._fileobj2output[self.stdout] AttributeError: 'Popen' object has no attribute '_fileobj2output'

I have not been able to reproduce this in a simple example, but I imagine this could happen if Popen._communicate() raises an exception in the first 20 lines or so--this would cause _communication_started to be set True, even though _fileobj2output has not been initialized.

I suggest setting self._fileobj2output = None in Popen.__init__() and changing the relevant code in _communicate() from

            if not self._communication_started:
                self._fileobj2output = {}

to:

            if self._fileobj2output is None:
                self._fileobj2output = {}
234a2386-3440-4ad4-a9a9-2b5f29559ce9 commented 7 years ago

Update: this appears to be the prior exception that causes _communication_started and _fileobj2ouput to be out of sync:

File "/usr/lib/python3.5/subprocess.py", line 1072, in communicate stdout, stderr = self._communicate(input, endtime, timeout) File "/usr/lib/python3.5/subprocess.py", line 1672, in _communicate self.stdin.flush() ValueError: flush of closed file

akulakov commented 1 year ago

I can reproduce with the following code, in version 3.12, which involves closing stdin before first communicate() so that you get the exception in _communicate(), and then try to communicate again when communicate again when _communication_started=True but the fileobj attr was not set because of the exception.

I'm not sure that's a realistic example that needs a fix. If someone can demonstrate that it IS a realistic scenario, the fix would be easy, along the lines OP suggested.

from subprocess import Popen, PIPE

p=Popen('ls', stdin=PIPE, stdout=PIPE)
p.stdin.close()
try:
    p.communicate()
except:
    pass
p.communicate()

Traceback (most recent call last):
  File "/Users/ak/opensource/cpython4/a.py", line 25, in <module>
    p.communicate()
  File "/Users/ak/opensource/cpython4/Lib/subprocess.py", line 1208, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ak/opensource/cpython4/Lib/subprocess.py", line 2035, in _communicate
    stdout = self._fileobj2output[self.stdout]
             ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Popen' object has no attribute '_fileobj2output'
HenryXiaoYang commented 2 weeks ago

Encountered this issue, any idea?

result = subprocess.Popen(f"{self.windows_wechat_start_path} {self.dll_path} {self.port}", shell=True,
                                  stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8')
result = ''.join(result.communicate())
logger.debug(result)
  File "C:\Users\Henry\Desktop\XYBot\pywxdll\pywxdll.py", line 54, in windows_start_wechat_and_inject
    result = ''.join(result.communicate())
AttributeError: 'CompletedProcess' object has no attribute 'communicate'