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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top