Pregunta

Estoy escribiendo un programa demonio usando Python 2.5. En el proceso principal, se registra un controlador de salida con el módulo atexit, parece que se llama al controlador cuando finaliza cada proceso secundario, lo cual no es lo que esperaba.

Noté que este comportamiento no se menciona en python <=> doc, ¿alguien sabe el problema? Si así es como debería comportarse, ¿cómo puedo cancelar el registro del controlador de salida en los procesos secundarios? Hay un atexit.unregister en la versión 3.0, pero estoy usando 2.5.

¿Fue útil?

Solución

No hay una API para hacerlo en Python 2.5, pero puedes simplemente:

import atexit
atexit._exithandlers = []

en sus procesos secundarios: si sabe que solo tiene un controlador de salida instalado y que no hay otros controladores instalados. Sin embargo, tenga en cuenta que algunas partes de stdlib (p. Ej., logging) registran atexit controladores. Para evitar pisotearlos, puedes intentar:

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)

donde my_handler_func es el <=> controlador que registró, y esto debería eliminar su entrada sin eliminar las demás.

Otros consejos

Cuando fork realiza un proceso secundario, ese elemento secundario es una copia exacta del elemento primario, incluidas, por supuesto, las funciones de salida registradas, así como todas las demás estructuras de código y datos. Creo que ese es el problema que está observando, por supuesto, no se menciona en todos y cada uno de los módulos, porque necesariamente se aplica a cada uno.

atexit.register() básicamente registra su función en atexit._exithandlers, que es una lista privada de funciones del módulo llamada por sys.exitfunc(). Puede configurar exitfunc() a su función de controlador de salida personalizada, que luego verifica el estado secundario o simplemente lo anula. ¿Qué hay de copiar el 3.0 atexit.py a su árbol de origen local y usarlo en su lugar?

EDITAR: copié el atexit.py de mi versión 2.6 y lo extendí

def unregister(func, *targs, **kargs):
    _exithandlers.remove((func, targs, kargs))

Si toma eso en lugar de su versión original, debería funcionar. Sin embargo, no lo he probado con subprocesos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top