如何在except子句中比较异常

时间:2009-05-12 03:20:08

标签: python exception

在以下代码段中:

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不能按预期工作,因为raise对象不是socket.timeout的实例,它是我们的一个代理助手类的实例。

5 个答案:

答案 0 :(得分:6)

我相信您的猜测在比较的工作方式上是正确的,并且拦截的唯一方法是将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:行重写为

... except (Bob, Fred):

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

答案 1 :(得分:1)

  

我希望能够构建一个Bob   这样它就被execpt抓住了   弗雷德即使它实际上不是   弗雷德或其任何一个的例子   子类。

好吧,你可以抓住'Exception' - 但这不是非常pythonic。您应该尝试捕获正确的异常,然后作为最后的手段回退到一般的异常(所有异常都是子类)。如果这对您不起作用,那么在您的设计阶段就会出现严重错误。

See this note from Code Like A Pythonista

  

注意:始终指定例外   抓住。切勿使用裸露的条款。   除了条款外,裸露的东西都会被捕获   意想不到的异常,让你的   代码非常难以调试。

然而,Python的Zen中的一个成语是

  

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

答案 2 :(得分:1)

>>> 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)的逻辑

看,这是你想要实现的方式,你想要的watever。当然不是在 init 中,而是在其他一些方法中。

>>> class Bob(Exception):
    def __init__(self):
        raise Fred

>>> try:
    b = Bob()
except Fred:
    print('blah')


blah

答案 3 :(得分:1)

我不清楚如何将socket.timeout中的异常隐藏到“无缝”理念中?捕获预期异常有什么问题?

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

或者,如果你真的想把它作为socket.timeout捕获,为什么不在just_proxy_helper_class中引发socket.timeout?

raise socket.timeout('Method x timeout')

因此,当你在our_proxy_helper_class中引发socket.timeout时,它应该被'除了socket.timeout'所捕获。

答案 4 :(得分:0)

至少在Python中,看起来有一个类型为10的COMPARE_OP操作(异常匹配)。你不可能做任何事情来破解这个计算。

>>> 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