是否可以从刚刚引发异常的方法访问对象?

Shi*_*kan 0 python exception

例如这段代码:

def foo():
    x = 5
    raise

def bar():
    try:
        foo()
    except:
        # access x here
Run Code Online (Sandbox Code Playgroud)

是否可以以某种方式访问​​ x ?谢谢。

Mar*_*ark 5

根据您的用例,更明智的方法是创建自定义异常并为其提供数据:

class MyException(Exception):
    def __init__(self, x, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.x = x

def foo():
    x = 5
    raise MyException(x)

def bar():
    try:
        foo()
    except MyException as e:
        print(e.x)
Run Code Online (Sandbox Code Playgroud)

如果您确实需要能够访问所有局部变量,则可以遍历异常的回溯以检索每个堆栈帧的局部变量。这是一个适合您的特定示例的简单示例:

def bar():
    try:
        foo()
    except Exception as e:  # BaseException if you want to catch *everything*
        frame = e.__traceback__.tb_next.tb_frame
        print(frame.f_locals["x"])
Run Code Online (Sandbox Code Playgroud)

通常,下一帧不一定是引发异常的帧。您可以遍历直到到达该框架,如下所示:

import traceback

def bar():
    try:
        foo()
    except Exception as e:
        # Get the last frame yielded, which will be where the exception was raised.
        *_, (frame, _) = traceback.walk_tb(e.__traceback__)
        print(frame.f_locals["x"])
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果您捕获对异常的引用,则也可以通过异常的“__traceback__”属性访问回溯。 (4认同)
  • 我认为这就是在“try”语句结束后隐式删除“e”(“ except”子句中的捕获变量)(就像使用“ del e”)的原因,以避免此类循环。异常对象保留对回溯的引用,但框架将不包含对异常的引用。 (3认同)
  • @chepner [gc devguide](https://devguide.python.org/garbage_collector/#identifying-reference-cycles) 也提到它作为循环的第一个示例:“异常包含回溯对象,其中包含包含帧的列表异常本身”。 (2认同)