Класс в реальном приложении отвечает за регистрацию некоторых своих методов (которые внутренне используют член записи файла) в качестве обратных вызовов для обработки связи MQTT и за создание нового средства записи журнала (по сути, оболочки файлового потока).
У автора файла есть финализатор, который закрывает файл, у основного класса есть финализатор, который отменяет регистрацию обратных вызовов (он также отключается от клиента paho MQTT и отписывается от тем, но это не так. актуально).
Я понимаю, что финализатор средства записи журнала не может быть вызван до тех пор, пока не будет вызван финализатор основного класса, поскольку методы, зарегистрированные как обратные вызовы, все еще ссылаются на средство записи журнала. Чего я не понимаю, так это того, почему финализаторы вообще не вызываются.
Я попытался воспроизвести проблему на фиктивном примере. Здесь 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 возникает исключение PermissionError, вынуждающее интерпретатор завершить работу, что приводит к окончательному выполнению предыдущих финализаторов.
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
Подробнее здесь: https://stackoverflow.com/questions/792 ... e-collecte
Регистрация метода в качестве обратного вызова предотвращает сбор мусора для объекта даже при использовании финализатора ⇐ Python
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение