Наследуется ли зарегистрированный обработчик atexit порожденными дочерними процессами?

StackOverflow https://stackoverflow.com/questions/1052716

  •  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))

Если вы возьмете это вместо своей оригинальной версии, это должно сработать.Однако я не тестировал это с помощью подпроцессов.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top