Python 什么可以防止回溯被垃圾收集?

Python 什么可以防止回溯被垃圾收集?,python,python-3.x,memory-leaks,clr,Python,Python 3.x,Memory Leaks,Clr,我无法显示太多代码,但请参见以下示例: class Product(metaclass=abc.ABCMeta): __attributes__ = [] __special_attributes__ = [] __json_additional_attributes__ = [] def __init__(self, original_object): for attribute in [c_attr for c_attr in self.__

我无法显示太多代码,但请参见以下示例:

class Product(metaclass=abc.ABCMeta):
    __attributes__ = []
    __special_attributes__ = []
    __json_additional_attributes__ = []

    def __init__(self, original_object):
        for attribute in [c_attr for c_attr in self.__attributes__
                            if c_attr not in self.__special_attributes__]:
            try:
                if hasattr(original_object, attribute):
                    # ...
                elif original_object.IsAttributeUsed(attribute):
                    # RAISES HERE - this is a clr binding
                    # ...
            except Exception as err:
                print('cant retrieve attr ' + attribute)

    # ...
为了简洁起见,我删除了一些行。这里,原始_对象是从clr绑定获得的对象。有时
original\u object.IsAttributeUsed(属性)
会在DLL端引发异常。异常按预期在except块中捕获

问题是:出于某种原因,它会泄漏内存,因为此异常的回溯对象从未被收集。回溯保留对堆栈中整个帧的引用,而堆栈中的帧又引用所有局部帧。这是一个批处理,所以这个堆栈可以容纳8Gb的内存,所以我很快就用光了内存

多亏了objgraph包,我得到了引用的图形,从泄漏对象到回溯对象的引用路径,然后什么都没有。如果没有引发异常,则释放内存

以下是图表:


对不起,我的图像太大了。左边的堆栈是我在玩调试器,别介意。我已经突出显示了泄漏。

查看是否执行了
import gc
然后执行
gc.collect()
是否仍然看到泄漏?@MSeifret是,甚至在调用clr时也是如此gc@martineau我没有在任何地方引用回溯,为什么我需要删除它?在Python 3中,在创建异常时会将回溯附加到异常(请参见),因此,您不需要显式调用
sys.exc_info()
来创建引用。您的代码有一个存储在局部变量
err
中。根据:回溯包含对所有活动帧的引用,而活动帧又包含对这些不同帧中所有局部变量的引用。您可以只使用
而不使用异常:
来避免此问题。请查看是否执行了
导入gc
,然后执行
gc.collect()
是否仍然看到泄漏?@MSeifret是,甚至在调用clr时也是如此gc@martineau我没有在任何地方引用回溯,为什么我需要删除它?在Python 3中,创建异常时会将回溯附加到异常(请参见),因此不需要显式调用
sys.exc\u info()
来创建引用。您的代码有一个存储在局部变量
err
中。根据:回溯包含对所有活动帧的引用,而活动帧又包含对这些不同帧中所有局部变量的引用。您可以只使用
而不使用Exception:
来避免此问题。