Наследуется ли зарегистрированный обработчик atexit порожденными дочерними процессами?
-
20-08-2019 - |
Вопрос
Я пишу демоническую программу, используя python 2.5.В основном процессе обработчик выхода регистрируется с atexit
модуль, он кажется что обработчик вызывается при завершении каждого дочернего процесса, чего я не ожидал.
Я заметил, что такое поведение не упоминается в python atexit
док, кто-нибудь знает о проблеме?Если это так, как это должно себя вести, как я могу отменить регистрацию обработчика выхода в дочерних процессах?В версии 3.0 есть файл atexit.unregister, но я использую 2.5.
Решение
В Python 2.5 нет API для этого, но вы можете просто:
import atexit
atexit._exithandlers = []
в ваших дочерних процессах - если вы знаете, что у вас установлен только один обработчик выхода и что никакие другие обработчики не установлены.Однако имейте в виду, что некоторые части stdlib (например logging
) зарегистрироваться atexit
обработчики.Чтобы не растоптать их, вы могли бы попробовать:
my_handler_entries = [e for e in atexit._exithandlers if e[0] == my_handler_func]
for e in my_handler_entries:
atexit._exithandlers.remove(e)
где my_handler_func
является ли atexit
обработчик, который вы зарегистрировали, и это должно удалить вашу запись, не удаляя остальные.
Другие советы
Когда ты fork
чтобы создать дочерний процесс, этот дочерний процесс является точной копией родительского - включая, конечно, зарегистрированные функции выхода, а также все остальные структуры кода и данных.Я полагаю, что это проблема, которую вы наблюдаете - конечно, она упоминается не в каждом модуле, потому что она обязательно применима к каждому отдельному модулю.
atexit.register()
в основном регистрирует вашу функцию в atexit._exithandlers
, который представляет собой закрытый список функций модуля , вызываемых sys.exitfunc()
.Вы можете установить exitfunc()
к вашей пользовательской функции обработчика выхода, которая затем проверяет наличие дочернего статуса или просто отменяет его регистрацию.Как насчет простого копирования версии 3.0 atexit.py
к вашему локальному дереву исходных текстов и используете это вместо этого?
Редактировать:Я скопировал atexit.py из моей версии 2.6 и расширил ее на
def unregister(func, *targs, **kargs):
_exithandlers.remove((func, targs, kargs))
Если вы возьмете это вместо своей оригинальной версии, это должно сработать.Однако я не тестировал это с помощью подпроцессов.