Варианты использования для __del__

Каковы варианты использования в python 3 написания пользовательского метода __del__ или использования одного из stdlib 1 ? То есть, в каком сценарии это разумно безопасно, и может сделать что-то, что трудно сделать без него?

По многим причинам ( 1 2 3 4 5 6 ) обычно рекомендуется избегать __del__ и вместо этого использовать контекстные менеджеры или выполнять очистку вручную:

  1. __del__ не гарантируется, что вызывается, если объекты живы на выходе 2 intrepreter.
  2. В точке можно ожидать, что объект может быть уничтожен, количество ссылок может фактически быть ненулевым (например, ссылка может выжить через кадр трассировки, удерживаемый вызывающей функцией). Это делает время разрушения гораздо более неопределенным, чем подразумевается простая непредсказуемость gc .
  3. Сборщик мусора не может избавиться от циклов, если они включают более 1 объекта с __del__
  4. Код внутри __del__ должен быть написан супер тщательно:
    • атрибуты объектов, установленные в __init__ могут отсутствовать, поскольку __init__ мог бы создать исключение;
    • исключения игнорируются (печатаются только на stderr );
    • globals больше не могут быть доступны.

Обновить:

PEP 442 значительно __del__ поведение __del__ . Кажется, что мои пункты 1-4 все еще действительны?


Обновление 2:

Некоторые из лучших библиотек python охватывают использование __del__ в __del__ post-PEP 442 (т. Е. Python 3.4+). Я предполагаю, что моя точка 3 больше не действует после PEP 442, а остальные точки принимаются как неизбежная сложность завершения объекта.


1 Я расширил вопрос только от написания настраиваемого метода __del__ чтобы включить использование __del__ из stdlib.

2 Кажется, что __del__ всегда вызывается на выходе интерпретатора в более поздних версиях Cpython (есть ли у кого-нибудь контр-пример?). Тем не менее, это не имеет значения для __del__ __del__: документы явно не дают никаких гарантий относительно этого поведения , поэтому нельзя полагаться на него (он может измениться в будущих версиях, и он может быть другим в интерпретаторах, отличных от CPython ).

3 Solutions collect form web for “Варианты использования для __del__”

Контекстные менеджеры (и try / finally blocks) несколько более ограничительны, чем __del__ . В общем, они требуют, чтобы вы структурировали свой код таким образом, чтобы ресурс ресурса, который вам нужен для свободного, не выходил за пределы одного вызова функции на некотором уровне в стеке вызовов, а не, скажем, привязывал его к жизни экземпляра класса, который может быть уничтожен в непредсказуемые времена и места. Обычно бывает полезно ограничить время жизни ресурсов одной областью, но иногда возникают случаи, когда этот шаблон неудобен.

Единственный случай, когда я использовал __del__ (кроме отладки, ответ cf @ MSeifert), предназначен для освобождения памяти, выделенной вне Python внешней библиотекой. Из-за дизайна библиотеки, которую я обертывал, было трудно избежать наличия большого количества объектов, содержащих указатели на выделенную кучу память. Использование метода __del__ для освобождения указателей было самым простым способом очистки, поскольку было бы нецелесообразно включать продолжительность каждого экземпляра в диспетчере контекстов.

Одним из вариантов использования является отладка. Если вы хотите отслеживать время жизни конкретного объекта, удобно написать временный метод __del__ . Его можно использовать для выполнения некоторых протоколов или для print . Я использовал его несколько раз, особенно когда мне было интересно, когда и как удаляются экземпляры. Иногда бывает полезно знать, когда вы создаете и отбрасываете много временных экземпляров. Но, как я уже сказал, я использовал это только для удовлетворения моего любопытства или отладки.

Другим вариантом использования является подкласс класса, который определяет метод __del__ . Иногда вы обнаруживаете класс, который вы хотите использовать для подкласса, но внутренняя часть требует, чтобы вы фактически переопределили __del__ для управления порядком, в котором этот экземпляр был очищен. Это очень редко, потому что вам нужно найти класс с __del__ , вы должны подклассифицировать его, и вам нужно ввести некоторые внутренние __del__ , которые на самом деле требуют вызова суперкласса __del__ в нужное время. Я действительно сделал это один раз, но я не помню, где и почему это было важно (возможно, я даже не знал об альтернативах, поэтому рассматривайте это как возможный случай использования).

Когда вы обертываете внешний объект (например, объект c, который не отслеживается Python), который действительно действительно должен быть освобожден, даже если кто-то «забывает» (я подозреваю, что многие люди просто опускают их специально!) Для использования который вы предоставили.


Однако все эти случаи (или должны быть) очень, очень редки. На самом деле это немного похоже на метаклассы: они забавные, и это действительно здорово понять концепции, потому что вы можете исследовать «забавные части» python. Но на практике:

Если вы задаетесь вопросом, нужны ли вам эти [метаклассы], вы этого не делаете (люди, которые действительно нуждаются в них, знают с уверенностью, что они в них нуждаются, и не нуждаются в объяснении, почему).

Цитата (вероятно) от Тима Петерса (я не нашел исходную ссылку).

Один случай, когда я всегда использую __del__ , предназначен для закрытия объекта aiohttp.ClientSession .

Когда вы этого не сделаете, aiohttp напечатает предупреждения о незакрытом сеансе клиента.

  • Косинус сходства между 2-мя списками
  • Как я могу реализовать asyncio websockets в классе?
  • Автоматическое преобразование типов пользовательских классов
  • Что такое __weakref__ в Python?
  • Как выполнить мою программу, если она встречает None в ее параметре в python
  • Python Как распечатать список списка
  • Python namedtuple как аргумент обратного вызова apply_async (..)
  • Как закодировать текст на base64 в python
  • asyncio.ensure_future vs. BaseEventLoop.create_task против простой сопрограммы?
  • TypeError: '<' не поддерживается между экземплярами 'tuple' и 'str'
  • Python 3.2 tkinter создает рамку результатов для вывода вывода
  •  
    Interesting Posts for Van-Lav

    Matplotlib B1-Motion (движение мыши с нажатой клавишей) эквивалентно?

    AttributeError: объект DjangoStrategy не имеет атрибута 'backend' python social auth

    Добавить маржу, когда графики выполняются против края графика

    AttributeError при использовании Django Rest Framework с сериализаторами

    RuntimeError: не удалось завершить работу тестового сервера в течение 2 секунд. Сервер может застрять или генерировать медленный ответ. – Django

    Интеграция Java Python

    Вычисление аналогичного цвета с помощью python

    Почему я не могу «сохранить как» файл Excel из моего кода на Python?

    Как комбинировать python asyncio с потоками?

    python math, numpy модули разные результаты?

    Python: вытягивание данных из словаря, как 2D-массив

    Почему обнаружение движения WxPythons так медленно?

    Я не понимаю Jinja2 Call Blocks

    QWebException: «Объект« NoneType »не может быть вызван» при оценке

    Пользовательский трансформатор для sklearn Pipeline, который изменяет как X, так и y

    Python - лучший язык программирования в мире.