python:如果后台线程处于活动状态,则不会运行weakref.finalize

问题描述 投票:0回答:2

当对象不在视线范围内时,我想使用weakref.finalize清理一些后台线程,但当对象在模块范围内时,终结器不会运行(编辑:)。

但请注意,该对象没有引用活动线程,我看不出它是不被垃圾收集的原因。

del的明确调用解决了这个问题,但这很不方便。

现场演示:https://ideone.com/kTZsbs

import weakref
import threading


def do(l):
    l.acquire()


class A:
    def __init__(self):
        l = threading.Lock()
        l.acquire()
        t = threading.Thread(target=do, args=[l])
        t.start()

        weakref.finalize(self, A._finalize, t, l)

    @staticmethod
    def _finalize(t, l):
        print("finalizing")
        l.release()
        t.join()


a = A()
# del a does trigger _finalize though
python multithreading garbage-collection
2个回答
1
投票

正如@quamrana所指出的,模块级对象只在卸载模块时才收集垃圾,因此当解释器在实践中退出时。

不幸的是,活动线程也存在于加载的线程模块中,引用计数> 0,这会阻止当前模块被卸载,因此对象不会被垃圾收集......

因此,确保对象是gc的唯一方法是对变量进行范围调整或确保线程自行超时。


0
投票

你只需要一种让a超出范围的方法:

def main():
    a = A()
    # when main exits, a will be garbage collected

main()

输出:

finalizing
© www.soinside.com 2019 - 2024. All rights reserved.