Регистрация метода в качестве обратного вызова предотвращает сбор мусора для объекта даже при использовании финализатораPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Регистрация метода в качестве обратного вызова предотвращает сбор мусора для объекта даже при использовании финализатора

Сообщение Anonymous »

Класс в реальном приложении отвечает за регистрацию некоторых своих методов (которые внутренне используют член записи файла) в качестве обратных вызовов для обработки связи 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
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»