Каковы варианты использования python 3 для написания пользовательского метода __del__ или использования одного из stdlib 1? То есть, в каком сценарии он разумно безопасен и может сделать что-то, что трудно сделать без него?
По многим причинам (1 2 3 4 5 6), обычно рекомендуется избегать __del__ и вместо этого использовать контекстные менеджеры или выполнять очистку вручную:
-
__del__не может быть вызван, если объекты живы на выходе intrepreter 2. - В точке ожидают, что объект может быть уничтожен, количество ссылок может фактически быть ненулевым (например, ссылка может выжить через кадр трассировки, удерживаемый вызывающей функцией). Это делает время разрушения гораздо более неопределенным, чем подразумевается простая непредсказуемость
gc. - Сборщик мусора не может избавиться от циклов, если они включают более одного объекта с
__del__ - Код внутри
__del__должен быть написан супер тщательно:- атрибуты объектов, установленные в
__init__, могут отсутствовать, так как__init__может вызвать исключение; - исключения игнорируются (печатаются только на
stderr); - globals могут быть недоступны.
- атрибуты объектов, установленные в
Update:
PEP 442 значительно улучшил поведение __del__. Кажется, что мои баллы 1-4 все еще действительны?
Обновление 2:
Некоторые из лучших библиотек python охватывают использование __del__ в питоне post-PEP 442 (то есть, python 3.4+), Я предполагаю, что моя точка 3 больше не действует после PEP 442, а остальные точки принимаются как неизбежная сложность завершения объекта.
1 Я расширил вопрос только от написания пользовательского метода __del__, включив в него __del__ из stdlib.
2 Кажется, что __del__ всегда вызывается на выходе интерпретатора в более поздних версиях Cpython (есть ли у кого-нибудь встречный пример?). Однако для целей __del__ usablity не имеет значения: документы явно не дают никаких гарантий относительно этого поведения, поэтому нельзя полагаться (он может измениться в будущих версиях, и он может отличаться у не-CPython-переводчиков).