下面的两个代码段都做同样的事情。它们捕获每个异常并执行except:块中的代码

片段1 -

try:
    #some code that may throw an exception
except:
    #exception handling code

片段2 -

try:
    #some code that may throw an exception
except Exception as e:
    #exception handling code

这两种构造的确切区别是什么?


当前回答

except:

接受所有异常,而

except Exception as e:

只接受你想要捕捉的异常。

这里有一个你不应该听的例子:

>>> try:
...     input()
... except:
...     pass
... 
>>> try:
...     input()
... except Exception as e:
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

第一个使KeyboardInterrupt静音!

下面是一个简短的列表:

issubclass(BaseException, BaseException)
#>>> True
issubclass(BaseException, Exception)
#>>> False


issubclass(KeyboardInterrupt, BaseException)
#>>> True
issubclass(KeyboardInterrupt, Exception)
#>>> False


issubclass(SystemExit, BaseException)
#>>> True
issubclass(SystemExit, Exception)
#>>> False

如果你想抓住其中任何一个,最好这样做

except BaseException:

指出你知道自己在做什么。


所有的异常都源于BaseException,而那些你每天都要捕捉的异常(那些将被抛出给程序员的异常)也继承自Exception。

其他回答

有一些例外的区别,例如KeyboardInterrupt。

阅读PEP8:

裸except:子句将捕获SystemExit和KeyboardInterrupt 异常,使得用Control-C中断程序更加困难, 还能掩盖其他问题。如果您想捕获所有异常 说明信号程序错误,使用except Exception:(裸except是 等价于except BaseException:)。

换个角度看。查看异常的详细信息:

In [49]: try: 
    ...:     open('file.DNE.txt') 
    ...: except Exception as  e: 
    ...:     print(dir(e)) 
    ...:                                                                                                                                    
['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__suppress_context__', '__traceback__', 'args', 'characters_written', 'errno', 'filename', 'filename2', 'strerror', 'with_traceback']

使用“as e”语法可以访问很多“东西”。

这段代码仅用于显示该实例的详细信息。

使用第二个代码片段为您提供了一个异常块范围内的变量(在示例e中根据as子句命名),并将异常对象绑定到该变量上,这样您就可以使用异常中的信息(类型、消息、堆栈跟踪等)在更专门的庄园中处理异常。

except:

接受所有异常,而

except Exception as e:

只接受你想要捕捉的异常。

这里有一个你不应该听的例子:

>>> try:
...     input()
... except:
...     pass
... 
>>> try:
...     input()
... except Exception as e:
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

第一个使KeyboardInterrupt静音!

下面是一个简短的列表:

issubclass(BaseException, BaseException)
#>>> True
issubclass(BaseException, Exception)
#>>> False


issubclass(KeyboardInterrupt, BaseException)
#>>> True
issubclass(KeyboardInterrupt, Exception)
#>>> False


issubclass(SystemExit, BaseException)
#>>> True
issubclass(SystemExit, Exception)
#>>> False

如果你想抓住其中任何一个,最好这样做

except BaseException:

指出你知道自己在做什么。


所有的异常都源于BaseException,而那些你每天都要捕捉的异常(那些将被抛出给程序员的异常)也继承自Exception。

第二步,你可以访问异常对象的属性:

>>> def catch():
...     try:
...         asd()
...     except Exception as e:
...         print e.message, e.args
... 
>>> catch()
global name 'asd' is not defined ("global name 'asd' is not defined",)

但它不会捕获BaseException或系统退出异常SystemExit, KeyboardInterrupt和GeneratorExit:

>>> def catch():
...     try:
...         raise BaseException()
...     except Exception as e:
...         print e.message, e.args
... 
>>> catch()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in catch
BaseException

一个bare except所做的:

>>> def catch():
...     try:
...         raise BaseException()
...     except:
...         pass
... 
>>> catch()
>>> 

更多信息请参见文档的内置异常部分和教程的错误和异常部分。