我正在将eventlet用于绿色线程(特别是wsgi服务器)。为了轻松地将此功能添加到现有代码库中,我使用了eventlet的monkey_patch功能。
因此,我文件的最上面是:
import eventlet
eventlet.monkey_patch()
我现在有一个功能远一点:
def ping(host: str) -> bool:
try:
ret = subprocess.check_output(["ping", "-c", "4", host], stderr=subprocess.DEVNULL).decode("utf-8")
for line in ret.splitlines()[1:-3]:
if host in line:
return True
return False
except subprocess.CalledProcessError:
return False
如果无法达到目标,则此功能的行为会使我感到困惑。如果未启用monkey_patch,则将返回False
,正如我期望的那样。但是,如果它们安装了monkey_patch,则会引发CalledProcessError
。
我不知道怎么可能-应该立即抓住它。这是怎么回事?
编辑1: 这是一个示例解释器会话:
>>> ping("192.168.0.233")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 8, in ping
ret = subprocess.check_output(["ping", "-c", "4", host], stderr=subprocess.DEVNULL).decode("utf-8")
File "/usr/lib/python3.6/subprocess.py", line 336, in check_output
**kwargs).stdout
File "/usr/lib/python3.6/subprocess.py", line 418, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['ping', '-c', '4', '192.168.0.233']' returned non-zero exit status 1.
编辑2:
事实证明,如果我用except Exception
甚至是裸露的except
捕获了异常,该异常就会被很好地捕获。我想我将使用它直到找到更合适的解决方案。但是,我仍然对这种行为感到震惊。
答案 0 :(得分:0)
问题是stdlib和绿色补丁模块中两个具有相同名称的不同异常类对象。在代码中,它们看起来相同,但是对于try/except
,它们是不同的类型。
对不起,暂时没有稳定的解决方案。欢迎打补丁!
解决方法:在执行任何其他代码之前调用eventlet.monkey_patch()
。
在此处订阅有关此问题的新闻:https://github.com/eventlet/eventlet/issues/413
根本原因是猴子修补程序会创建一个新模块,将已知名称“复制”到其中,同时替换到绿色模块的链接,并将该模块在stdlib名称下放入sys.modules
中。 (与就地修改stdlib模块相反,这是不可能的,因为Python C-API限制)