Подтвердить что ты не робот

Где документируется процедура выключения Python?

CPython имеет странное поведение, когда он устанавливает модули в None во время выключения. Это приводит к сбою регистрации ошибок во время выключения некоторого кода многопоточности, который я написал.

Я не могу найти документацию по этому поведению. Он упоминал попутно в PEP 432:

[...] значительно уменьшает количество модулей, которые будут испытывать поведение "глобальные глобальные модули" на "Нет", которое используется для преднамеренного прерывания циклов и попытки очистить больше внешних ресурсов.

Есть вопросы SO о таком поведении и Документация C API упоминает поведение выключения для встроенных переводчики.

Я также нашел связанный поток на python-dev и связанная ошибка CPython:

Этот патч не изменяет поведение модуля объекты, очищающие словарь глобалов, как только они освобождаются.

Где такое поведение задокументировано? Является ли это Python 2 конкретным?

4b9b3361

Ответ 1

Поведение плохо документировано и присутствует во всех версиях Python примерно с 1,5-и до тех пор, пока Python 3.4:

Как часть этого изменения, глобальные глобальные модули больше не принудительно устанавливаются на None во время остановки интерпретатора в большинстве случаев, вместо этого полагаясь на обычную работу циклического сборщика мусора.

Единственной документацией для поведения является moduleobject.c исходный код:

/* To make the execution order of destructors for global
   objects a bit more predictable, we first zap all objects
   whose name starts with a single underscore, before we clear
   the entire dictionary.  We zap them by replacing them with
   None, rather than deleting them from the dictionary, to
   avoid rehashing the dictionary (to some extent). */

Обратите внимание, что установка значений None является оптимизацией; альтернативой будет удаление имен из сопоставления, что приведет к различным ошибкам (NameError исключения, а не AttributeError при попытке использовать глобальные переменные из обработчика __del__).

Как вы узнали в списке рассылки, поведение предшествует циклическому сборщику мусора; это было добавлено в 1998 году, в то время как циклический сборщик мусора был добавлен в 2000 году. Поскольку объектные объекты всегда ссылаются на модуль __dict__, все объекты функции в модуле связаны с круговыми ссылками, поэтому требуется перед тем, как GC начнет играть.

Он поддерживался на месте, даже когда был добавлен циклический GC, поскольку в цикле могут быть объекты с __del__. Эти не могут собирать мусор, а очистка словаря модуля, по крайней мере, приведет к удалению модуля __dict__ из таких циклов. Не делая этого, все ссылки на глобальные модули этого модуля будут сохранены.

Изменения, сделанные для PEP 442, теперь позволяют сборщику мусора очищать циклические ссылки с объектами, которые предоставляют финализатор __del__, устраняя необходимость очистки модуль __dict__ для большинства случаев. Код все еще существует, но это срабатывает только в том случае, если атрибут __dict__ еще сохраняется даже после перемещения содержимого sys.modules на слабые ссылки и запуск коллекции GC запускать, когда интерпретатор выключается; модуль-финализатор модуля просто уменьшает счетчик ссылок.

Ответ 2

В нижней части документации по потокам есть небольшая документация, связанная с документацией:

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