Документация Python C API сообщает мне, что tp_dealloc
может быть вызван с ошибкой, и в качестве примера дает разматывание стека из-за исключения:
Одним из важных требований функции deallocator является то, что она оставляет все ожидающие исключения в покое. Это важно, поскольку деаллокаторы часто вызываются, поскольку интерпретатор раскручивает стек Python; когда стек разматывается из-за исключения (а не из-за нормальных возвратов), ничего не делается, чтобы защитить освобождающие блоки от просмотра того, что исключение уже установлено. Любые действия, которые выполняет освобождение, которые могут вызвать выполнение дополнительного кода Python, могут обнаружить, что установлено исключение. Это может привести к вводящим в заблуждение ошибкам интерпретатора.
Однако мне кажется, что я не могу воспроизвести это поведение в CPython 3.6 на Ubuntu:
import sys
def raise_error():
raise ValueError("Boom!")
def try_me():
obj = sys.Custom()
raise_error()
def run():
try:
try_me()
except ValueError as e:
print('VE')
print(e)
return
run()
print('42')
В этом примере obj
не освобождается до тех пор, пока не завершится run
(на хосте C создается тип Custom
с пользовательским tp_dealloc
, который печатает «err» или «no err» в зависимости от значения, возвращаемого PyErr_Occurred
).
Вот что он печатает:
VE
Boom!
no err
42
Является ли этот пункт документации устаревшим? Если нет, как я могу воспроизвести упомянутый там сценарий (например, когда tp_dealloc
вызывается с установленной ошибкой)?