首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何测试由保存的异常引起的引用周期?

如何测试由保存的异常引起的引用周期?
EN

Stack Overflow用户
提问于 2021-04-19 07:05:08
回答 2查看 53关注 0票数 2

我说的是这个问题:https://bugs.python.org/issue36820

小摘要:

保存异常会导致循环引用,因为异常的数据包括带有保存异常的变量的堆栈帧的跟踪。

代码语言:javascript
复制
try:
    1/0
except Exception as e:
    ee = e

代码没有中断,因为Python最终会用垃圾收集器释放内存。但可以避免整个选址:

代码语言:javascript
复制
try:
    1/0
except Exception as e:
    ee = e
    ...
    ...
finally:
    ee = None

在链接的bpo-36820中,有一个弱引用的演示保持了活力。

我的问题是,是否存在不需要编辑函数本身的测试。有点像

  • 运行经过测试的函数
  • ,检查是否创建了新的循环

gc模块能做到这一点吗?

EN

回答 2

Stack Overflow用户

发布于 2022-12-04 04:01:09

是的,使用gc模块,我们可以检查是否有(新的)异常仅由跟踪帧引用。

在实践中,迭代gc对象会创建一个额外的引用程序(不能将WeakSet作为内置异常使用--内置的异常不支持弱引用),因此我们检查是否有两个引用器--框架和附加引用程序。

代码语言:javascript
复制
def get_exception_ids_with_reference_cycle(exclude_ids=None):
    import gc
    import types
    exclude_ids = () if exclude_ids is None else exclude_ids
    exceptions = [
        o for o in gc.get_objects(generation=0)
        if isinstance(o, Exception) and id(o) not in exclude_ids
    ]
    exception_ids = [
        id(e) for e in exceptions
        if len(gc.get_referrers(e)) == 2 and all(
            isinstance(r, types.FrameType) or r is exceptions
            for r in gc.get_referrers(e)
        )
    ]
    return exception_ids

用法:

代码语言:javascript
复制
exception_ids = get_exception_ids_with_reference_cycle()
x()
print(bool(get_exception_ids_with_reference_cycle(exclude_ids=exception_ids)))

替代用法:

代码语言:javascript
复制
@contextlib.contextmanager
def make_helper():
    exception_ids = get_exception_ids_with_reference_cycle()
    yield lambda: bool(get_exception_ids_with_reference_cycle(exclude_ids=exception_ids))


with make_helper() as get_true_if_reference_cycle_was_created:
    x()
    print(get_true_if_reference_cycle_was_created())
票数 2
EN

Stack Overflow用户

发布于 2022-12-02 19:15:15

我相信你可以使用gc模块来做这样的事情。

代码语言:javascript
复制
import gc

# First, enable garbage collection
gc.enable()

# Save an exception to a variable
exception = Exception('test exception')

# Check for objects that are no longer being referenced by the program
if gc.garbage:
  # Print the objects that are causing the cycle
  print(gc.garbage)

  # Use the gc.get_referrers method to find out what objects
  # are causing the cycle
  for obj in gc.garbage:
    print(gc.get_referrers(obj))

  # Modify your code to break the cycle
  # (This will depend on your specific code and the objects
  # involved in the cycle)
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67157372

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档