python - CalledProcessError 使用 eventlet 越过 try 块
问题描述
我将 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
甚至是一个bare捕获异常except
,异常就会被很好地捕获。我想我会使用它,直到找到更合适的解决方案。然而,我仍然对这种行为感到目瞪口呆。
解决方案
问题是 stdlib 和绿色补丁模块中具有相同名称的两个不同的异常类对象。在代码中它们看起来相同,但try/except
它们是不同的类型。
抱歉,目前没有稳定的解决方案。欢迎打补丁!
解决方法:eventlet.monkey_patch()
在执行任何其他代码之前调用。
在此处订阅有关此问题的新闻:https ://github.com/eventlet/eventlet/issues/413
根本原因是猴子补丁创建了一个新模块,将已知名称“复制”到其中,同时替换绿色模块的链接并将该模块放在 stdlib 名称下的sys.modules
. (与就地修改 stdlib 模块相反,因为 Python C-API 限制,这是不可能的)
推荐阅读
- amazon-web-services - 我可以从我的 lambda 函数触发 AWS AppSync 中的订阅事件吗?
- python - 从熊猫列的列表中删除单词 - python 2.7
- regex - RegEx not recognized although it should be
- php - SQL条件下的内爆数组和字符串连接问题
- r - 基于日期的计算
- css - 使用 Less CSS 复制样式
- php - 在一行中从变量名和命名空间启动一个实例
- google-apps-script - 我可以在 Google 幻灯片插件中创建顶级菜单吗?
- authentication - AntiforgeryToken 验证失败
- postgresql - Postgres中不同模式之间的SpringBoot 2 JPA关系