Daemonizing BaseHTTPServer de python

Estoy trabajando en un demonio donde necesito incrustar un servidor HTTP. Estoy intentando hacerlo con BaseHTTPServer, que cuando lo ejecuto en primer plano, funciona bien, pero cuando bash separar el daemon en segundo plano, deja de funcionar. Mi aplicación principal sigue funcionando, pero BaseHTTPServer no lo hace.

Creo que esto tiene algo que ver con el hecho de que BaseHTTPServer envía datos de registro a STDOUT y STDERR. Los estoy redirigiendo a archivos. Aquí está el fragmento de código:

# Start the HTTP Server server = HTTPServer((config['HTTPServer']['listen'],config['HTTPServer']['port']),HTTPHandler) # Fork our process to detach if not told to stay in foreground if options.foreground is False: try: pid = os.fork() if pid > 0: logging.info('Parent process ending.') sys.exit(0) except OSError, e: sys.stderr.write("Could not fork: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) # Second fork to put into daemon mode try: pid = os.fork() if pid > 0: # exit from second parent, print eventual PID before print 'Daemon has started - PID # %d.' % pid logging.info('Child forked as PID # %d' % pid) sys.exit(0) except OSError, e: sys.stderr.write("Could not fork: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) logging.debug('After child fork') # Detach from parent environment os.chdir('/') os.setsid() os.umask(0) # Close stdin sys.stdin.close() # Redirect stdout, stderr sys.stdout = open('http_access.log', 'w') sys.stderr = open('http_errors.log', 'w') # Main Thread Object for Stats threads = [] logging.debug('Kicking off threads') while ... lots of code here ... server.serve_forever() 

¿Estoy haciendo algo mal aquí o se impide que BaseHTTPServer se vuelva demonizado?

Edición: Código actualizado para demostrar el flujo de código adicional que faltaba anteriormente y que log.debug muestra en mi daemon de fondo bifurcado Estoy golpeando código después de bifurcación.

    Después de un poco de googlear, finalmente me topé con esta documentación de BaseHTTPServer y después de eso terminé con:

     from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from SocketServer import ThreadingMixIn class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): """Handle requests in a separate thread.""" server = ThreadedHTTPServer((config['HTTPServer']['listen'],config['HTTPServer']['port']), HTTPHandler) server.serve_forever() 

    Que en su mayor parte viene después de que bifurque y termine resolviendo mi problema.

    Aquí se explica cómo hacer esto con la biblioteca del daemon de python :

     from BaseHTTPServer import (HTTPServer, BaseHTTPRequestHandler) import contextlib import daemon from my_app_config import config # Make the HTTP Server instance. server = HTTPServer( (config['HTTPServer']['listen'], config['HTTPServer']['port']), BaseHTTPRequestHandler) # Make the context manager for becoming a daemon process. daemon_context = daemon.DaemonContext() daemon_context.files_preserve = [server.fileno()] # Become a daemon process. with daemon_context: server.serve_forever() 

    Como es habitual en un demonio, debe decidir cómo interactuará con el progtwig una vez que se convierta en un demonio. Por ejemplo, puede registrar un servicio systemd, o escribir un archivo PID, etc. Sin embargo, todo eso está fuera del scope de la pregunta.

    Comienzas por crear una instancia de un servidor HTTPS. Pero en realidad no le dices que comience a servir en ninguno de los códigos suministrados. En su proceso hijo intente llamar a server.serve_forever() .

    Vea esto para referencia

    Una solución simple que funcionó para mí fue anular el método log_message() , por lo que evitamos cualquier tipo de escritura en la BaseHTTPRequestHandler log_message() y evitamos problemas al demonizar.

     class CustomRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): def log_message(self, format, *args): pass ... rest of custom class code ... 

    Simplemente use daemontools o algún otro script similar en lugar de rodar su propio proceso de demonización. Es mucho mejor mantener esto fuera de tu guión.

    Además, su mejor opción: No use BaseHTTPServer. Es realmente malo Hay muchos buenos servidores HTTP para python, es decir, cherrypy o pegar . Ambos incluyen scripts de demonización listos para usar.

    Ya que esto ha solicitado respuestas desde que publiqué originalmente, pensé que compartiría un poco de información.

    El problema con la salida tiene que ver con el hecho de que el controlador predeterminado para el módulo de registro utiliza StreamHandler. La mejor manera de manejar esto es crear tus propios manejadores. En el caso de que desee utilizar el módulo de registro predeterminado, puede hacer algo como esto:

     # Get the default logger default_logger = logging.getLogger('') # Add the handler default_logger.addHandler(myotherhandler) # Remove the default stream handler for handler in default_logger.handlers: if isinstance(handler, logging.StreamHandler): default_logger.removeHandler(handler) 

    También en este punto me he movido a usar el muy agradable proyecto Tornado para mis servidores http integrados.