我正在研究第三方开发人员使用的Python库,为我们的核心应用程序编写扩展。

我想知道在引发异常时是否可以修改回溯,因此最后一个堆栈帧是在开发人员代码中调用库函数,而不是引发异常的库中的行。堆栈底部还有一些框架,其中包含对第一次加载我想要删除的代码时使用的函数的引用。

提前感谢任何建议!

有帮助吗?

解决方案

如何不改变追溯?您要求的两件事情都可以通过不同的方式更轻松地完成。

  1. 如果来自库的异常被开发人员的代码捕获并且引发了新的异常,那么原来的回溯当然会被抛出。这就是异常通常被处理的方式......如果你只是允许引发原始异常,但是你想要删除所有的“上层”异常。帧,实际的异常没有意义,因为回溯中的最后一行本身不能引发异常。
  2. 要去掉最后几帧,你可以请求缩短你的追溯......像traceback.print_exception()这样的东西需要一个“限制”。您可以用来跳过最后几个条目的参数。
  3. 那就是说,如果你真的需要,那么应该很有可能进行回溯......但是你会在哪里做呢?如果在最高级别的某些包装器代码中,那么您可以简单地抓取回溯,取一个切片来移除您不想要的部分,然后使用“追溯”中的函数。模块根据需要进行格式化/打印。

其他提示

您可以通过使用traceback的tb_next元素进行提升来轻松删除回溯的顶部:

except:
    ei = sys.exc_info()
    raise ei[0], ei[1], ei[2].tb_next

tb_next是一个read_only属性,所以我不知道从底部删除东西的方法。您可能可以使用属性机制来允许访问该属性,但我不知道该怎么做。

看看jinja2在这里做了什么:

https://github.com/mitsuhiko/jinja2/blob /5b498453b5898257b2287f14ef6c363799f1405a/jinja2/debug.py

这很难看,但似乎做了你需要做的事情。我不会在这里复制粘贴示例,因为它很长。

您可能也对 PEP-3134 感兴趣在python 3中,允许您将一个异常/回溯添加到上游异常中。

这与修改追溯并不完全相同,但它可能是传达“短版”的理想方式。对于库用户而言仍然具有“长版本”可用。

此代码可能对您有用。

它需要一个回溯并删除第一个不应显示的文件。然后它模拟Python行为:

Traceback (most recent call last):
仅当回溯包含多个文件时才会显示

。 这看起来就好像我的额外框架不在那里。

这是我的代码,假设有一个字符串 text

try:
    exec(text)
except:
    # we want to format the exception as if no frame was on top.
    exp, val, tb = sys.exc_info()
    listing = traceback.format_exception(exp, val, tb)
    # remove the entry for the first frame
    del listing[1]
    files = [line for line in listing if line.startswith("  File")]
    if len(files) == 1:
        # only one file, remove the header.
        del listing[0]
    print("".join(listing), file=sys.stderr)
    sys.exit(1)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top