英文:
Can python `except` match against all errors in the chain?
问题
以下是翻译好的部分:
我有一个Python应用程序,它构建了一个具有多个 raise from
子句的长错误链。我想要定义一个特定的 except
块来捕捉可能深入链中发生的一个值。看起来 Python 的 except
只会检查链中的第一个错误。是否有一种类似于 Go 中的 errors.is
的标准方法来遍历这个链?
示例:
class CustomException1(Exception):
pass
class CustomException2(Exception):
pass
class CustomException3(Exception):
pass
def func_1():
try:
raise Exception("test failure")
except Exception:
raise CustomException1()
def func_2():
try:
func_1()
except Exception as e:
raise CustomException2() from e
def func_3():
try:
func_2()
except Exception as e:
raise CustomException3() from e
def func_4():
try:
func_3()
except CustomException1:
print("为 CustomException1 执行特定操作")
pass
except Exception:
print("通用异常处理程序")
pass
func_4()
我运行了上面的代码,看到输出是 "通用异常处理程序"。我想要异常与 CustomException1
子句匹配。是否有一种标准方法来遍历这个链?
英文:
I have a python application which constructs a long error chain with multiple raise from
clauses. I'm interested defining a specific except
block to catch one of the values that may occur deep within the chain. It appears that python except
only checks against the first error in the chain. Is there a standard way to traverse the chain similar to errors.is
in go?
Example:
class CustomException1(Exception):
pass
class CustomException2(Exception):
pass
class CustomException3(Exception):
pass
def func_1():
try:
raise Exception("test failure")
except Exception:
raise CustomException1()
def func_2():
try:
func_1()
except Exception as e:
raise CustomException2() from e
def func_3():
try:
func_2()
except Exception as e:
raise CustomException3() from e
def func_4():
try:
func_3()
except CustomException1:
print("do something specific for CustomException1")
pass
except Exception:
print("general exception handler")
pass
func_4()
I ran the above code and saw the output "general exception handler". I'd like the exception to be matched by CustomException1
clause. Is there a standard method for traversing the chain?
答案1
得分: 2
从Python 3.11开始,您可以使用异常组来将多个异常打包成一个具有任意结构的单个包。在这里,我们仍然保留了调用堆栈所暗示的线性结构,但我们不需要显式遍历该链以查找类型为CustomeException1
的异常。(尽管您可以:except*
是用于使用其API操作捕获的ExceptionGroup
的语法糖,包括subgroup
、split
和derive
方法。)
class CustomException1(Exception): pass
class CustomException2(Exception): pass
class CustomException3(Exception): pass
def func_1():
raise CustomException1()
def func_2():
try:
func_1()
except Exception as e:
raise ExceptionGroup("from func_2", [CustomException2(), e])
def func_3():
try:
func_2()
except ExceptionGroup as eg:
raise ExceptionGroup("from func3", [CustomException3(), eg])
def func_4():
try:
func_3()
except* CustomException1:
print("do something specific for CustomException1")
except* Exception:
print("general exception handler")
func_4()
当您运行此脚本时,将看到以下输出:
do something specific for CustomException1
general exception handler
请注意,except*
子句从可能在层次结构中的任何位置提取CustomException1
;捕获器不需要手动解析异常组(尽管可以使用split
方法进行解析,这就是except*
在其实现中使用的方法)。还要注意,与except
不同,except*
可以在每个处理程序执行后继续匹配异常。
英文:
Starting in Python 3.11, you can use exception groups to package multiple exceptions into a single package with arbitrary structure. Here, we're still preserving the linear structure implied by the call stack, but we don't need to explicitly traverse that chain to find an exception of type CustomeException1
. (Though you can: except*
is syntactic sugar for manipulating a caught ExceptionGroup
using its API, including the subgroup
, split
, and derive
methods.)
class CustomException1(Exception): pass
class CustomException2(Exception): pass
class CustomException3(Exception): pass
def func_1():
raise CustomException1()
def func_2():
try:
func_1()
except Exception as e:
raise ExceptionGroup("from func_2", [CustomException2(), e])
def func_3():
try:
func_2()
except ExceptionGroup as eg:
raise ExceptionGroup("from func3", [CustomException3(), eg])
def func_4():
try:
func_3()
except* CustomException1:
print("do something specific for CustomException1")
except* Exception:
print("general exception handler")
func_4()
When you run the script, you'll see the following output:
do something specific for CustomException1
general exception handler
Note that the except*
clause extracts CustomException1
from wherever in the hierarchy it may be found; the catcher need not parse the exception group manually (though it is possible using the split
method, which is what except*
uses in its implementation.) Also note that unlike except
, except*
can continue matching exceptions after each handler has executed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论