CalledProcessError通过带有事件小程序的尝试块

时间:2018-08-01 02:40:09

标签: python exception eventlet

我正在将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捕获了异常,该异常就会被很好地捕获。我想我将使用它直到找到更合适的解决方案。但是,我仍然对这种行为感到震惊。

1 个答案:

答案 0 :(得分:0)

问题是stdlib和绿色补丁模块中两个具有相同名称的不同异常类对象。在代码中,它们看起来相同,但是对于try/except,它们是不同的类型。

对不起,暂时没有稳定的解决方案。欢迎打补丁!

解决方法:在执行任何其他代码之前调用eventlet.monkey_patch()

在此处订阅有关此问题的新闻:https://github.com/eventlet/eventlet/issues/413

根本原因是猴子修补程序会创建一个新模块,将已知名称“复制”到其中,同时替换到绿色模块的链接,并将该模块在stdlib名称下放入sys.modules中。 (与就地修改stdlib模块相反,这是不可能的,因为Python C-API限制)