【发布时间】:2016-02-15 20:23:38
【问题描述】:
我有一些 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()
我正在尝试遵循the python subprocess documentation here中描述的原则,即在出现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来重现这个问题吗? -
这是在 3.6.0 中重现此问题的代码:` import 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)`
标签: python python-3.x io subprocess