在Python中捕获所有异常

44

在Python中,捕获“所有”异常的最佳方式是什么?

except: # do stuff with sys.exc_info()[1]

except BaseException as exc:

except Exception as exc:

可能的异常捕获可能在线程中执行。

我的目标是记录正常代码可能抛出的任何异常,而不掩盖任何特殊的Python异常,例如指示进程终止等异常。

获取异常句柄(例如包含exc的上述子句)也是可取的。

3个回答

69
  • except Exception:except BaseException: 的区别:

    捕获 ExceptionBaseException 的区别在于,根据异常继承层次结构,像 SystemExit、KeyboardInterrupt 和 GeneratorExit 这样的异常在使用 except Exception 时不会被捕获,因为它们直接继承自 BaseException

  • except:except BaseException: 的区别:

    这两者的区别主要在 Python 2 中(据我所知),并且仅当使用旧式类作为要引发的异常时才会出现,此时只有没有表达式的 except 子句才能捕获异常,例如:

  • class NewStyleException(Exception): pass
    
    try:
       raise NewStyleException
    except BaseException:
       print "Caught"
    
    class OldStyleException: pass
    
    try:
       raise OldStyleException
    except BaseException:
       print "BaseException caught when raising OldStyleException"
    except:
       print "Caught"
    

2
我让NewStyleException继承自Exception,这是官方推荐的做法(http://docs.python.org/tutorial/errors.html#user-defined-exceptions)。 - Eric O. Lebigot

32

如果您需要捕获所有异常并对它们执行相同的操作,我建议您使用以下代码:

try:
   #stuff
except:
   # do some stuff

如果您不想掩盖“特殊”的Python异常,请使用Exception基类。

try:
   #stuff
except Exception:
   # do some stuff

对于与异常管理相关的某些异常,请显式捕获它们:

try:
   #stuff
except FirstExceptionBaseClassYouWantToCatch as exc:
   # do some stuff
except SecondExceptionBaseClassYouWantToCatch as exc:
   # do some other stuff based
except (ThirdExceptionBaseClassYouWantToCatch, FourthExceptionBaseClassYouWantToCatch) as exc:
   # do some other stuff based

来自python文档的异常层次结构应该是一个有用的阅读材料。


2
感谢提供异常层次结构的链接。 :) - Eric O. Lebigot
如果未定义except类,我该如何获取捕获的异常实例? - mvorisek
@Mvorisek 使用 except Exception as exc,Exception 是所有异常的基类,因此它可以捕获任何异常。 - Cédric Julien

-1
为了避免掩盖基本异常,您需要“重新引发”任何不是您明确想要处理的异常,例如(改编自8. 错误和异常):

import sys

try: # do something that could throw an exception: except IOError as (errno, strerror): print "I/O error({0}): {1}".format(errno, strerror) except ValueError: print "Could not convert data to an integer." except: # maybe log the exception (e.g. in debug mode) # re-raise the exception: raise


4
最终的 except: raise 不执行任何操作:可以完全跳过;非 IOError 和非 ValueError 异常不会被捕获,而是由解释器自动引发。 - Eric O. Lebigot
3
你说得对。我已经编辑了我的答案,说明为什么最后的 except: 可能是有用的。 - Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接