代码之家  ›  专栏  ›  技术社区  ›  Gordon Wrigley

except子句中的异常如何比较

  •  -2
  • Gordon Wrigley  · 技术社区  · 15 年前

    在以下代码段中:

    try:
        raise Bob()
    except Fred:
        print "blah"
    

    Bob和Fred的比较是如何实现的?

    从玩转的角度看,它似乎在下面称为IsInstance,这是正确的吗?

    我之所以这样问是因为我试图颠覆这个过程,特别是我希望能够构建一个Bob,这样它就可以被execpt fred捕获,即使它实际上不是fred或其任何子类的实例。

    有几个人问我为什么要这么做…

    我们有一个RMI系统,它是围绕着使其尽可能无缝的理念构建的,这里有一个使用中的它的快速示例,注意在RMI系统中没有特定于套接字的代码,套接字只是提供了一个方便的示例。

    import remobj
    socket = remobj.RemObj("remote_server_name").getImport("socket")
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.bind(("", 0))
    print "listening on port:", s.getsockname()[1]
    s.settimeout(10)
    try:
        print "received:", s.recv(2048)
    except socket.timeout:
        print "timeout"
    

    现在在这个特定的例子中,except不能像预期的那样工作,因为引发的对象不是socket.timeout的实例,它是一个代理助手类的实例。

    5 回复  |  直到 15 年前
        1
  •  6
  •   Cassie Meharry    15 年前

    我相信你的猜测是正确的,在比较是如何工作的,唯一的拦截方法就是把fred作为基类添加到bob中。例如:

    # Assume both Bob and Fred are derived from Exception
    >>> class Bob(Bob, Fred):
    ...     pass
    ... 
    >>> try:
    ...     raise Bob()
    ... except Fred:
    ...     print 'blah'
    blah
    

    据我所知,这是你写作的唯一方法。但是,如果您只是重写了except:line-as

    ... except (Bob, Fred):
    

    它可以捕获Bob和Fred,而不需要修改Bob的定义。

        2
  •  1
  •   Shane C. Mason    15 年前

    我想能做一个鲍勃 让它被执行官抓住 弗雷德,尽管它实际上不是一个 Fred或其任何一个实例 子类。

    好吧,你可以抓住“例外”——但这不是很蟒蛇。您应该尝试捕获正确的异常,然后作为最后的手段返回到一般异常(所有异常都是从中子类化的)。如果这对您不起作用,那么在您的设计阶段就出现了严重的错误。

    See this note from Code Like A Pythonista

    注意:始终指定 渔获量。除条款外,不得使用裸句。 空的except子句将捕获 意外的例外,使 代码非常难调试。

    然而,在python的禅中有一个习语是

    特殊情况不足以打破规则。 尽管实用性胜过纯洁性。

        3
  •  1
  •   roopesh    15 年前
    >>> class Fred(Exception):
        pass
    >>> class Bob(Fred):
        pass
    >>> issubclass(Bob, Fred)
    True
    >>> issubclass(Fred, Bob)
    False
    >>> try:
        raise Bob()
    except Fred:
        print("blah")
    
    
    blah
    

    所以基本上,这个异常是被捕获的,因为Bob是Fred的子类,我假设,要么它们实现了类似于 issubclass(Bob, Fred)

    看,这就是你想要实现的方式,无论你想要什么。当然不是在 初始化 但是其他方法。

    >>> class Bob(Exception):
        def __init__(self):
            raise Fred
    
    >>> try:
        b = Bob()
    except Fred:
        print('blah')
    
    
    blah
    
        4
  •  1
  •   monkut    15 年前

    我不清楚如何将您的异常隐藏在socket.timeout中,从而遵循“无缝”的理念?按照定义捕获预期的异常有什么问题?

    try:
        print "received:", s.recv(2048)
    except socket.timeout:
        print "timeout"
    except our_proxy_helper_class:
        print 'crap!'
    

    或者,如果您真的想把它作为socket.timeout捕获,为什么不在我们的\proxy\u helper\u类中提高socket.timeout?

    raise socket.timeout('Method x timeout')
    

    因此,当您在我们的“代理”助手类中提升socket.timeout时,它应该被“except socket.timeout”捕获。

        5
  •  0
  •   Sufian    15 年前

    至少在cpython中,似乎有一个与类型10(异常匹配)的比较操作。你不太可能做任何事情来绕过这个计算。

    >>> import dis
    >>> def foo():
    ...     try:
    ...             raise OSError()
    ...     except Exception, e:
    ...             pass
    ... 
    >>> dis.dis(foo)
      2           0 SETUP_EXCEPT            13 (to 16)
    
      3           3 LOAD_GLOBAL              0 (OSError)
                  6 CALL_FUNCTION            0
                  9 RAISE_VARARGS            1
                 12 POP_BLOCK           
                 13 JUMP_FORWARD            21 (to 37)
    
      4     >>   16 DUP_TOP             
                 17 LOAD_GLOBAL              1 (Exception)
                 20 COMPARE_OP              10 (exception match)
                 23 JUMP_IF_FALSE            9 (to 35)
                 26 POP_TOP             
                 27 POP_TOP             
                 28 STORE_FAST               0 (e)
                 31 POP_TOP             
    
      5          32 JUMP_FORWARD             2 (to 37)
            >>   35 POP_TOP             
                 36 END_FINALLY         
            >>   37 LOAD_CONST               0 (None)
                 40 RETURN_VALUE