我有一些类似于这样的Python 3.5代码:
try:
my_process = Popen(someargs, stdin=None, stdout=PIPE, stderr=PIPE)
stdout, stderr = my_process.communicate(timeout=10)
my_process.wait()
except TimeoutExpired:
my_process.kill()
stdout, stderr = my_process.communicate()
我正在尝试遵循Python子进程文档中描述的原则,链接在此处:https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate,即在出现TimeoutError的情况下,我应该手动终止进程,然后完成通信。
原则上这听起来不错,但是定期(大约每50次中的1次左右)我会收到以下错误消息:
Traceback (most recent call last):
File "/Users/xyz/myprogram/myprogram", line 125, in <module>
stdout, stderr = my_process.communicate()
File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/subprocess.py", line 1068, in communicate
stdout, stderr = self._communicate(input, endtime, timeout)
File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/subprocess.py", line 1689, in _communicate
selector.register(self.stdout, selectors.EVENT_READ)
File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/selectors.py", line 342, in register
key = super().register(fileobj, events, data)
File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/selectors.py", line 228, in register
key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/selectors.py", line 215, in _fileobj_lookup
return _fileobj_to_fd(fileobj)
File "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/python3.5/selectors.py", line 39, in _fileobj_to_fd
"{!r}".format(fileobj)) from None
ValueError: Invalid file object: <_io.BufferedReader name=5>
在我的情况下,第125行是第二个communicate()
行。
看起来这个失败是因为某些流已关闭或终止 - 也许有时在kill()
和communicate()
之间发生了这种情况?但如果是这样的话,我应该如何优雅地处理它呢?Python文档似乎没有涵盖这种情况。
child.py
文件,并传入someargs
来重现这个问题? - jfsimport subprocess import time po = subprocess.Popen(['/bin/ls'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) time.sleep(1) out, err = po.communicate(timeout=1) out, err = po.communicate(timeout=1)
- mattismyname