对所有捕获的异常执行常见操作的 Pythonic 方式
Pythonic way of doing common actions for all catched exceptions
如果我有以下结构:
try:
do_something_dangerous()
except Exception1:
handle_exception1()
handle_all_exceptions()
except Exception2:
handle_exception2()
handle_all_exceptions()
...
如果我不想在每个 except
子句中调用 handle_all_exceptions
,那么调用 handle_all_exceptions
的最 Pythonic 方法是什么,因为我有很多这样的子句?也许有一种简单的方法可以确定异常是否发生在 finally
子句中?
我能想到的最简单的方法是嵌套 try 语句:
try:
try:
do_something_dangerous()
except Exception1:
handle_exception1()
raise
except Exception2:
handle_exception2()
raise
except Exception:
handle_all_exceptions()
裸 raise
重新引发异常。
另一种选择是捕获所有异常并进行自己的调度,而不是为此使用 try
语句:
try:
do_something_dangerous()
except Exception as e:
if isinstance(e, Exception1):
handle_exception1()
if isisntance(e, Exception2):
handle_exception2()
handle_all_exceptions()
我认为您还可以检查异常的类型。但是,我不知道这是不是最pythonic的方式:
编辑: 查看文档,似乎没有最pythonic的方法。如何处理函数 handle_all_exceptions()
中的不同类型的异常取决于您。 See the doc.
try:
do_something_dangerous()
except Exception as e:
handle_all_exceptions(e)
def handle_all_exceptions(e):
if isinstance(e, Exception1):
handle_exception1()
elif isinstance(e, Exception2):
handle_exception2()
由于您不想检查实例或类似物,这里是另一种可能的实现方式。虽然列表实现肯定不是很好,但它解决了没有嵌套 try 语句的问题。您也可以使用布尔语句或类似语句,但是使用列表,您仍然可以访问错误对象以进行进一步处理。
ex = []
try:
do_something_dangerous()
except Exception1 as e:
ex.append(e)
handle_exception1()
except Exception2 as e:
ex.append(e)
handle_exception2()
finally:
if ex: handle_all_exceptions(ex)
您可以先定义一个映射关联处理函数与相应的异常:
err_handling = {
Exception1: handle_exception1
Exception2: handle_exception2
# ...
}
然后您可以接受引发的异常作为 handle_all_exceptions
函数的参数,并使用处理映射和引发的异常类型为其添加特定处理。
def handle_all_exceptions(err):
# common exception handling
err_handling[type(err)]()
这样做你可以以一种简单的方式处理你的异常:
try:
do_something_dangerous()
except Exception as err:
handle_all_exceptions(err)
我在每个 except
子句中找到了一些没有 type
、 isinstance
和大量 raise
的棘手解决方案。也许它不是最 Pythonic,但至少很有趣:
try:
do_something_dangerous()
except:
try:
raise
except Exception1:
handle_exception1()
except Exception2:
handle_exception2()
handle_all_exceptions()
如果我有以下结构:
try:
do_something_dangerous()
except Exception1:
handle_exception1()
handle_all_exceptions()
except Exception2:
handle_exception2()
handle_all_exceptions()
...
如果我不想在每个 except
子句中调用 handle_all_exceptions
,那么调用 handle_all_exceptions
的最 Pythonic 方法是什么,因为我有很多这样的子句?也许有一种简单的方法可以确定异常是否发生在 finally
子句中?
我能想到的最简单的方法是嵌套 try 语句:
try:
try:
do_something_dangerous()
except Exception1:
handle_exception1()
raise
except Exception2:
handle_exception2()
raise
except Exception:
handle_all_exceptions()
裸 raise
重新引发异常。
另一种选择是捕获所有异常并进行自己的调度,而不是为此使用 try
语句:
try:
do_something_dangerous()
except Exception as e:
if isinstance(e, Exception1):
handle_exception1()
if isisntance(e, Exception2):
handle_exception2()
handle_all_exceptions()
我认为您还可以检查异常的类型。但是,我不知道这是不是最pythonic的方式:
编辑: 查看文档,似乎没有最pythonic的方法。如何处理函数 handle_all_exceptions()
中的不同类型的异常取决于您。 See the doc.
try:
do_something_dangerous()
except Exception as e:
handle_all_exceptions(e)
def handle_all_exceptions(e):
if isinstance(e, Exception1):
handle_exception1()
elif isinstance(e, Exception2):
handle_exception2()
由于您不想检查实例或类似物,这里是另一种可能的实现方式。虽然列表实现肯定不是很好,但它解决了没有嵌套 try 语句的问题。您也可以使用布尔语句或类似语句,但是使用列表,您仍然可以访问错误对象以进行进一步处理。
ex = []
try:
do_something_dangerous()
except Exception1 as e:
ex.append(e)
handle_exception1()
except Exception2 as e:
ex.append(e)
handle_exception2()
finally:
if ex: handle_all_exceptions(ex)
您可以先定义一个映射关联处理函数与相应的异常:
err_handling = {
Exception1: handle_exception1
Exception2: handle_exception2
# ...
}
然后您可以接受引发的异常作为 handle_all_exceptions
函数的参数,并使用处理映射和引发的异常类型为其添加特定处理。
def handle_all_exceptions(err):
# common exception handling
err_handling[type(err)]()
这样做你可以以一种简单的方式处理你的异常:
try:
do_something_dangerous()
except Exception as err:
handle_all_exceptions(err)
我在每个 except
子句中找到了一些没有 type
、 isinstance
和大量 raise
的棘手解决方案。也许它不是最 Pythonic,但至少很有趣:
try:
do_something_dangerous()
except:
try:
raise
except Exception1:
handle_exception1()
except Exception2:
handle_exception2()
handle_all_exceptions()