atexit
— Обработчики выхода¶
Модуль atexit
определяет функции для регистрации и снятия с регистрации функций очистки. Зарегистрированные таким образом функции автоматически выполняются при обычном завершении работы интерпретатора. Модуль atexit
запускает эти функции в порядке, обратном тому, в котором они были зарегистрированы; если вы зарегистрируете A
, B
и C
, то при завершении работы интерпретатора они будут выполняться в порядке C
, B
, A
.
Примечание: Функции, зарегистрированные в этом модуле, не вызываются, когда программа завершается по сигналу, не обрабатываемому Python, когда обнаруживается фатальная внутренняя ошибка Python или когда вызывается os._exit()
.
Примечание: Эффект регистрации или снятия с регистрации функций изнутри функции очистки не определен.
Изменено в версии 3.7: При использовании с субинтерпретаторами C-API зарегистрированные функции являются локальными для интерпретатора, в котором они были зарегистрированы.
- atexit.register(func, *args, **kwargs)¶
Зарегистрируйте func как функцию, которая будет выполняться при завершении. Любые необязательные аргументы, которые должны быть переданы в func, должны быть переданы в качестве аргументов в
register()
. Одну и ту же функцию и аргументы можно зарегистрировать несколько раз.При обычном завершении программы (например, при вызове
sys.exit()
или завершении выполнения главного модуля) все зарегистрированные функции вызываются в порядке «последний вошел, первый вышел». Предполагается, что модули нижнего уровня обычно импортируются раньше модулей верхнего уровня и поэтому должны быть очищены позже.Если во время выполнения обработчиков выхода возникает исключение, печатается обратная трассировка (если только не возникло
SystemExit
) и сохраняется информация об исключении. После того как все обработчики выхода успеют выполниться, последнее поднятое исключение будет поднято повторно.Эта функция возвращает func, что позволяет использовать ее в качестве декоратора.
Предупреждение
Запуск новых потоков или вызов
os.fork()
из зарегистрированной функции может привести к состоянию гонки между основным потоком выполнения Python, освобождающим состояние потока, и внутреннимиthreading
подпрограммами или новым процессом, пытающимся использовать это состояние. Это может привести к сбоям, а не к чистому завершению работы.Изменено в версии 3.12: Попытки запустить новый поток или
os.fork()
новый процесс в зарегистрированной функции теперь приводят кRuntimeError
.
- atexit.unregister(func)¶
Удалить func из списка функций, запускаемых при завершении работы интерпретатора.
unregister()
молча ничего не делает, если func не была зарегистрирована ранее. Если func была зарегистрирована более одного раза, будет удалено каждое вхождение этой функции в стеке вызововatexit
. Сравнение равенств (==
) используется внутренне при снятии с регистрации, поэтому ссылки на функции не обязательно должны иметь совпадающие идентификаторы.
См.также
atexit
Пример¶
Следующий простой пример демонстрирует, как модуль может инициализировать счетчик из файла при его импорте и автоматически сохранять обновленное значение счетчика при завершении программы, не требуя от приложения явного вызова этого модуля при завершении работы.
try:
with open('counterfile') as infile:
_count = int(infile.read())
except FileNotFoundError:
_count = 0
def incrcounter(n):
global _count
_count = _count + n
def savecounter():
with open('counterfile', 'w') as outfile:
outfile.write('%d' % _count)
import atexit
atexit.register(savecounter)
В register()
также могут быть переданы позиционные и ключевые аргументы, которые будут переданы зарегистрированной функции при ее вызове:
def goodbye(name, adjective):
print('Goodbye %s, it was %s to meet you.' % (name, adjective))
import atexit
atexit.register(goodbye, 'Donny', 'nice')
# or:
atexit.register(goodbye, adjective='nice', name='Donny')
Использование в качестве decorator:
import atexit
@atexit.register
def goodbye():
print('You are now leaving the Python sector.')
Это работает только с функциями, которые можно вызывать без аргументов.