Документация Python неофициальный перевод
Содержание страницы

atexit – Обработчики завершенияatexit – Exit handlers


Модуль 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 будет удалено. Сравнения на равенство (==) используются внутри процедуры отмены регистрации, поэтому ссылки на функцию не должны быть одинаковыми.

См. также

Модуль readline

Полезный пример использования atexit для чтения и записи readline файлов истории.

atexit Примерatexit Example

Следующий простой пример демонстрирует, как модуль может инициализировать счётчик из файла при импорте и автоматически сохранять обновлённое значение счётчика при завершении программы, не полагаясь на явный вызов этого модуля приложением при завершении.

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')
# или:
atexit.register(goodbye, adjective='nice', name='Donny')

Использование в качестве декоратора:

import atexit

@atexit.register
def goodbye():
    print('You are now leaving the Python sector.')

Это работает только с функциями, которые можно вызывать без аргументов.