我会以类似你所思考的方式进行,使用“你不能通过”
甘道夫异常处理程序
except Exception
来捕获所有非系统退出异常,同时创建一个黑名单
set
,其中包含应该通过并重新引发的异常。
使用
Gandalf 处理程序 可以确保
GeneratorExit
,
SystemExit
和
KeyboardInterrupt
(所有系统退出异常)会传递并在没有更高层调用堆栈中存在其他处理程序时终止程序。在这里,您可以通过
type(e)
检查捕获到的异常
e
的
__class__
是否实际属于黑名单异常集合,并重新
raise
它。
以下是一个小演示:
import exceptions
excptDict = vars(exceptions)
exceptionNames = ['MemoryError', 'OSError', 'SystemError']
blackSet = {excptDict[exception] for exception in exceptionNames}
现在
blackSet = {OSError, SystemError, MemoryError}
持有我们不想处理的非系统退出异常类。
一个
try-except
块现在可以看起来像这样:
try:
except Exception as e:
if type(e) in blackSet: raise e
一个使用BaseException
捕获所有异常的示例可以帮助说明我的意思。(此操作仅用于演示目的,以便查看如何终止程序)。请注意:我不建议您使用BaseException
;我使用它来演示实际会“通过”的异常是什么,并导致终止(即BaseException
捕获的一切内容):
for i, j in excptDict.iteritems():
if i.startswith('__'): continue
try:
try:
raise j
except Exception as ex:
if type(ex) in blackSet:
raise ex
except BaseException:
print "Handler 'BaseException' caught " + str(i)
Handler 'BaseException' caught GeneratorExit
Handler 'BaseException' caught OSError
Handler 'BaseException' caught SystemExit
Handler 'BaseException' caught SystemError
Handler 'BaseException' caught KeyboardInterrupt
Handler 'BaseException' caught MemoryError
Handler 'BaseException' caught BaseException
最后,为了使这个Python 2/3兼容,你可以使用
try
和
import exceptions
,如果失败了(在Python 3中会失败),就回退到导入
builtins
,其中包含所有的
Exceptions
;我们通过名称搜索字典,所以没有任何区别。
try:
import exceptions
excDict = vars(exceptions)
except ImportError:
import builtins
excDict = vars(builtins)
我不知道是否有更聪明的做法,另一个解决方案可能是,不使用带有单一except
的try-except
,而是使用两个处理程序,一个用于黑名单异常,另一个用于一般情况:
try:
except tuple(blackSet) as be:
raise be
except Exception as e: