注册为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
相关产品推荐
相关产品推荐

