如何修改sys.exc_info()的堆栈列表?

huangapple go评论90阅读模式
英文:

How do I modify the stack list of sys.exc_info()?

问题

我想要从堆栈列表中移除表示装饰器的一些帧然后再记录它但是当我尝试访问它时调试器说没有名为 `stack` 的属性尽管 PyCharm 显示它

```py
sys.exc_info()[2].tb_frame.stack  # < -- AttributeError,但为什么?

如何修改sys.exc_info()的堆栈列表?

这是我想要做的:

sys.exc_info()[2].tb_frame.stack = sys.exc_info()[2].tb_frame.stack[3:]

<details>
<summary>英文:</summary>

I&#39;d like to remove a couple of frames from the stack list that represent a decorator before logging it, but when I try to get to it, the debugger says that there is no such attribute as `stack` even though PyCharm shows it:

```py
sys.exc_info()[2].tb_frame.stack  # &lt;-- AttributeError, but why?

如何修改sys.exc_info()的堆栈列表?

This is what I would like to do:

sys.exc_info()[2].tb_frame.stack = sys.exc_info()[2].tb_frame.stack[3:]

答案1

得分: 3

对于Python 3.8版本中的traceback.tb_frame对象,我看不到stack属性:

try:
    raise Exception('test')
except:
    cls, e, tb = sys.exc_info()

hasattr(tb.tb_frame, 'stack')
False

你可以通过在回溯(traceback)上追踪tb_next属性,可能在for循环中执行此操作:

try:
    do_something()
except Exception as e:
    cls, exc, tb = sys.exc_info()

    for _ in range(3):
        tb_next = tb.tb_next

        # 如果没有那么多帧的情况
        if not tb_next:
            break

        tb = tb_next

    raise cls.with_traceback(tb)
英文:

FWIW, I can't see an attribute for stack on a traceback.tb_frame object in python 3.8:

try:
    raise Exception(&#39;test&#39;)
except:
    cls, e, tb = sys.exc_info()

hasattr(tb.tb_frame, &#39;stack&#39;)
False

You can probably do this in a for loop by tracing the tb_next attribute on the traceback:

try:
    do_something()
except Exception as e:
    cls, exc, tb = sys.exc_info()

    for _ in range(3):
        tb_next = tb.tb_next

        # in case you don&#39;t have that many frames
        if not tb_next:
            break

        tb = tb_next

    raise cls.with_traceback(tb)

答案2

得分: 0

stack 属性不是 Python 中 frame 对象的内置属性。看起来 PyCharm 提供了这个属性以方便调试,但它并不属于标准的 Python 库。

要实现从堆栈列表中移除几个帧以达到你期望的结果,你可以使用 traceback 模块直接操作回溯对象。下面是一个例子:

import traceback

try:
    # 在这里放置你的代码
    pass
except Exception as e:
    tb = e.__traceback__
    tb = tb.tb_next.tb_next  # 跳过两个帧
    e.__traceback__ = tb
    raise e

在这个例子中,我们访问异常对象 (e) 的 __traceback__ 属性来获取回溯对象。然后我们通过两次访问 tb_next 属性来跳过两个帧,然后将修改后的回溯对象赋值回 __traceback__。最后,我们重新引发异常以保留原始行为。

请注意,以这种方式修改回溯对象并不是一种常见的做法,应该谨慎使用。它可能会产生意想不到的后果,并使调试变得更加困难。

英文:

The stack attribute is not a built-in attribute of the frame object in Python. It seems that PyCharm is providing this attribute as a convenience for debugging purposes, but it is not part of the standard Python library.

To achieve your desired result of removing a couple of frames from the stack list, you can use the traceback module to manipulate the traceback object directly. Here's an example:

import traceback

try:
    # Your code here
    pass
except Exception as e:
    tb = e.__traceback__
    tb = tb.tb_next.tb_next  # Skip two frames
    e.__traceback__ = tb
    raise e

In this example, we access the __traceback__ attribute of the exception object (e) to get the traceback object. We then skip two frames by accessing the tb_next attribute twice, and assign the modified traceback object back to __traceback__. Finally, we re-raise the exception to preserve the original behavior.

Note that modifying the traceback object in this way is not a common practice and should be used with caution. It may have unexpected consequences and make debugging more difficult.

huangapple
  • 本文由 发表于 2023年7月18日 03:17:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76707499.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定