É manipulador atexit registrada herdado por processos filho gerados?
-
20-08-2019 - |
Pergunta
Eu estou escrevendo um programa daemon usando o Python 2.5. No processo principal um manipulador de saída é registrado com o módulo atexit
, ele parece que o manipulador é chamado quando cada processo filho extremidades, o que não eu esperava.
Eu observei este comportamento não é mencionado em python atexit
doc, ninguém sabe o problema? Se esta é a forma como ele deve se comportar, como posso cancelar o registro do manipulador de saída nos processos de crianças? Há uma atexit.unregister na versão 3.0, mas eu estou usando 2.5.
Solução
Não há uma API para fazê-lo em Python 2.5, mas você pode apenas:
import atexit
atexit._exithandlers = []
em seus processos filhos - se você sabe que só tem um manipulador de saída instalado, e que há outros manipuladores são instalados. No entanto, estar cientes de que algumas partes do stdlib (por exemplo logging
) registar manipuladores atexit
. Para evitar pisar sobre eles, você pode tentar:
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)
onde my_handler_func
é o manipulador atexit
se registou, e isso deve remover a sua entrada sem remover os outros.
Outras dicas
Quando você fork
para fazer um processo filho, essa criança é uma cópia exata do pai - incluindo de funções de saída curso registrados, bem como todas as outras estruturas de código e de dados. Eu acredito que esse é o problema que você está observando -. Claro que não é mencionado em cada módulo, porque necessariamente se aplica a cada um
atexit.register()
basicamente registra sua função em atexit._exithandlers
, que é uma lista privada módulo de funções chamadas por sys.exitfunc()
. Você pode definir exitfunc()
à sua função de manipulador de saída personalizado feito, o que, em seguida, verifica a condição de criança ou simplesmente cancela o registro dele. O que sobre apenas copiando o atexit.py
3.0 para sua árvore de fonte local e usar que em vez?
EDIT: eu copiei o atexit.py de minha versão 2.6 e extended por
def unregister(func, *targs, **kargs):
_exithandlers.remove((func, targs, kargs))
Se você levar isso em vez de sua versão original ele deve funcionar. Eu não testei com subprocessos, no entanto.