You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

注册为callback的方法导致对象无法被垃圾回收,finalizer完全不执行的问题求助

注册为callback的方法导致对象无法被垃圾回收,finalizer完全不执行的问题求助

大家好,我遇到了一个Python垃圾回收与finalizer执行相关的问题,想请教各位大佬帮忙分析。

在实际项目中,我有个主类负责两件事:一是把自身的部分方法(内部会用到文件写入成员)注册为MQTT通信的回调;二是实例化一个日志写入器(本质是文件流的包装类)。其中文件写入器的finalizer负责关闭文件,主类的finalizer则负责注销回调(还包含MQTT客户端断开、取消订阅逻辑,但这部分暂时不影响问题)。

我能理解,因为注册的回调方法还引用着日志写入器,所以日志写入器的finalizer要等主类的finalizer执行后才会被触发,但我搞不懂的是——这两个finalizer为什么完全不会主动执行?

我写了一个简化的复现示例,其中CallbackContainer只是用来在主类Supervisor外部保存可调用对象:

import os
from weakref import finalize
from collections.abc import Callable
from typing import Optional


class FileStreamWrapper:

    def __init__(self, file: str):
        if os.path.isfile(file):
            os.remove(file)
        file_stream = open(file, "w")

        def finalizer():
            file_stream.close()
            print("finalized 'FileStreamWrapper' object")

        finalize(self, finalizer)
        self._file_stream = file_stream

    def print_line(self, line: str):
        self._file_stream.write(line + "\n")


class CallbackContainer:

    def __init__(self):
        self._callback: Optional[Callable[[], None]] = None

    def register_callback(self, callback: Callable[[], None]):
        self._callback = callback

    def unregister_callback(self):
        self._callback = None


class Supervisor:

    def __init__(self):
        file_stream_wrapper = FileStreamWrapper("test.txt")
        callback_container = CallbackContainer()
        callback_container.register_callback(lambda : self._print_line(""))

        def finalizer():
            callback_container.unregister_callback()
            print("finalized 'Supervisor' object")

        finalize(self, finalizer)
        self._file_stream_wrapper = file_stream_wrapper
        self._callback_container = callback_container

    def _print_line(self, line: str):
        self._file_stream_wrapper.print_line(line)


if __name__ == '__main__':

    for _ in range(2):
        supervisor = Supervisor()
        del supervisor

我原本期望每次循环结束后,supervisor被删除后两个finalizer都会自动执行。但实际情况是,文件始终没有被关闭,创建第二个Supervisor实例时会抛出PermissionError,强制解释器退出,这时候之前的finalizer才终于被触发:

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'test.txt'
finalized 'FileStreamWrapper' object
finalized 'Supervisor' object

有没有大佬能帮我分析下这背后的原因?感谢各位的解答!

备注:内容来源于stack exchange,提问作者Vexx23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 17:58:07