[pyar] Logging en un proceso demonizado con DaemonRunner
Aníbal Lovaglio
aniballovaglio en yahoo.com.ar
Mie Ene 30 01:54:57 ART 2013
Hola a todos,
Tengo una aplicación en la cual, algunas de las
tareas están delegadas sobre un demonio, que construí usando
DaemonRunner (http://pydoc.net/python-daemon/1.4.2/daemon.runner), y
hasta ahora ha probado resolver mi problema bastante elegantemente. El
problema con el que me encontré es a la hora de agregarle un mecanismo
de log para poder darle seguimiento. Estuve investigando una librería
estándar que es exactamente lo que estaba buscando del paquete logging.
Cuando
pongo a correr el demonio, con las entradas de log dispuestas en el
código, estoy obteniendo el siguiente error (una vez por cada invocación
al log que se hace en el código).
Logged from file foo.py, line 48
Traceback (most recent call last):
File "/usr/lib/python2.7/logging/__init__.py", line 870, in emit
self.flush()
File "/usr/lib/python2.7/logging/__init__.py", line 832, in flush
self.stream.flush()
IOError: [Errno 9] Bad file descriptor
Por lo que leí, entiendo que se trata de un impedimento a la hora de
acceder al archivo por parte del logger, y sospecho que tiene que ver
con la demonización del proceso. Tengo entendido que el DaemonRunner,
antes de poner a correr el proceso demonio, cierra "todos los archivos
abiertos" por alguna cuestión sobre la que leí muchísimas veces,
honestamente sin entender realmente. De todas formas, el síntoma
concreto es este error. Dejo el código del controlador del demonio y el "administrador" de logger que escribí para uniformizar la configuración.
Desde ya cualquier ayuda es bienvenida. Muchas gracias!
daemon_control.py
[code]
#!/usr/bin/python
import time
from datetime import datetime
from daemon.runner import DaemonRunner
from seal import settings #your project settings file
from django.core.management import setup_environ #environment setup function
import argparse
from auto_correction.log.logger_manager import LoggerManager
setup_environ(settings)
from auto_correction.automatic_correction_runner import AutomaticCorrectionRunner
class LoopRunner():
LOOP_INTERVAL = 65
def __init__(self):
self.loop_interval = LoopRunner.LOOP_INTERVAL # in seconds
self.stdin_path = '/dev/null'
self.stdout_path = '/dev/tty'
self.stderr_path = '/dev/tty'
self.pidfile_path = '/tmp/foo.pid'
self.pidfile_timeout = 5
self.automatic_correction_runner = AutomaticCorrectionRunner()
self.log = LoggerManager().getLogger()
def stall_loop(self, start_timestamp, finish_timestamp):
delta = finish_timestamp - start_timestamp
time_to_wait = self.loop_interval - delta.seconds # if the process took less than 30 seconds, we will wait
if (time_to_wait > 0):
time.sleep(time_to_wait)
else:
print("not sleeping... delta: " + str(delta))
start_timestamp = datetime.today()
def print_result(self, result):
# TODO: pass to a log entry
print str(datetime.today()) + " | " + str(result)
def run(self):
self.log = LoggerManager().getLogger("daemon control")
self.log.info("Daemon's game loop started.")
while True:
start_timestamp = datetime.today()
result = self.automatic_correction_runner.run()
self.log.info(str(result))
finish_timestamp = datetime.today()
self.stall_loop(start_timestamp, finish_timestamp)
parser = argparse.ArgumentParser(description='Starts or stops the seal daemon.')
parser.add_argument('command', metavar='start/stop',
help='the command that should be executed on the daemon')
args = parser.parse_args()
logger_manager = LoggerManager()
log = logger_manager.getLogger()
log.info("Daemon action recived: '%s'", args.command)
loop_runner = LoopRunner()
daemon_runner = DaemonRunner(loop_runner) # runner.DaemonRunner(loop_runner)
daemon_runner.do_action()
if("start".__eq__(args.command.lower())):
log.info("Daemon launched.")
else:
log.info("Daemon stopped.")
[/code]
logger_manager.py
[code]
import logging
class LoggerManager:
LOGGER = None
# FIXME: This should be in a configuration file or otherwise not hardcoded
logfile = "/tmp/seal-daemon.log"
def getLogger(self, logname=None):
if(LoggerManager.LOGGER is None):
logging.basicConfig(filename=self.logfile, format='%(asctime)s - %(levelname)s: %(message)s', level=logging.DEBUG,
datefmt='%Y-%m-%d %H:%M:%S')
LoggerManager.LOGGER = logging.getLogger()
return LoggerManager.LOGGER
[/code]
Saludos!
Aníbal
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20130129/5af44938/attachment.html>
More information about the pyar
mailing list