tutorial framework python django logging

python - framework - django tutorial



Inicio de sesión de Python en Django (11)

Para responder la pregunta sobre por qué "Django importa settings.py varias veces": no es así.

En realidad, se importa dos veces (omita el primer fragmento de código para entrar en él, pero una buena lectura si tiene tiempo):

http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html

PD- Perdón por revivir un hilo viejo.

Estoy desarrollando una aplicación de Django, y estoy tratando de usar el módulo de registro de Python para el registro de error / rastreo. Idealmente, me gustaría tener diferentes registradores configurados para diferentes áreas del sitio. Hasta ahora tengo todo esto funcionando, pero una cosa me tiene a mí rascándome la cabeza.

Tengo el registrador de raíz yendo a sys.stderr, y he configurado otro registrador para escribir en un archivo. Esto está en mi archivo settings.py:

sviewlog = logging.getLogger(''MyApp.views.scans'') view_log_handler = logging.FileHandler(''C://MyApp//logs//scan_log.log'') view_log_handler.setLevel(logging.INFO) view_log_handler.setFormatter(logging.Formatter(''%(asctime)s %(name)-12s %(levelname)-8s %(message)s'')) sviewlog.addHandler(view_log_handler)

Parece bastante simple. Sin embargo, este es el problema: todo lo que escribo en el sviewlog se escribe en el archivo de registro dos veces. El registrador de raíz solo lo imprime una vez. Es como addHandler () se llama dos veces. Y cuando paso mi código a través de un depurador, esto es exactamente lo que veo. El código en settings.py se ejecuta dos veces, por lo que se crean y añaden dos FileHandlers a la misma instancia del registrador. ¿Pero por qué? ¿Y cómo me las arreglo?

¿Alguien puede decirme qué está pasando aquí? Intenté mover el código de creación de instancias de logger / gestor de sviewlog al archivo en el que se usa (ya que en realidad me parece el lugar adecuado), pero tengo el mismo problema allí. La mayoría de los ejemplos que he visto en línea usan solo el registrador de raíz, y preferiría tener varios registradores.


¿Por qué utilizar Python Logger en lugar de django-logging? Pruébalo, podría resolver tu problema.

http://code.google.com/p/django-logging/wiki/Overview

Por el momento, solo permitiría ver el registrador de raíz, pero puede escribir a múltiples registradores.


A partir de la versión 1.3, Django usa el registro de python estándar, configurado con la configuración LOGGING (documentado aquí: 1.3 , dev ).

Referencia de registro de Django: 1.3 , dev .


Difícil comentar sobre su caso específico. Si settings.py se ejecuta dos veces, entonces es normal que obtenga dos líneas por cada registro enviado.

Tuvimos el mismo problema, así que lo configuramos en nuestros proyectos para tener un módulo dedicado al registro. Los módulos tienen un patrón de "módulo único", por lo que solo ejecutaremos el código interesante una vez.

Se parece a esto:

def init_logging(): stdoutHandler = logging.StreamHandler( sys.stdout ) stdoutHandler.setLevel( DEBUG ) stdoutHandler.setFormatter( logging.Formatter( LOG_FORMAT_WITH_TIME ) ) logging.getLogger( LOG_AREA1 ).addHandler( stdoutHandler ) logInitDone=False #global variable controlling the singleton. if not logInitDone: logInitDone = True init_logging()

La importación de log.py la primera vez configurará el registro correctamente.


Para agregar a la publicación de A Lee , la documentación de inicio de sesión de Python indica esto sobre la propagación:

Logger.propagate

Si esto se evalúa como falso, los mensajes de registro no son pasados ​​por este registrador o por sus registradores hijo a los manejadores de registradores de nivel superior (ancestro). El constructor establece este atributo en 1.

Esto significa que si propagate == False , el registrador secundario NO pasará el mensaje de registro a su registrador padre


Para responder la pregunta sobre por qué "Django importa settings.py varias veces": no es así.

Probablemente esté ejecutando un servidor web multiproceso / multiproceso que crea varios subinterpretadores de Python, donde cada uno de ellos importa el código de su aplicación django una vez.

Pruébelo en el servidor de prueba django y verá que la configuración no se importa muchas veces.

Hace algún tiempo, diseñé un sencillo singleton (versión idiomática de borg pitón para ser más preciso) con mi primera aplicación django / apache, antes de darme cuenta rápidamente de que sí, tenía más de una instancia de mi singleton creado ...


Permíteme responder mi propia pregunta. El problema subyacente aquí es que settings.py se importa dos veces o incluso más (consulte here ). (Todavía no entiendo por qué es esto. Tal vez algún experto de Django podría explicarme eso). Esto también parece ser cierto para algunos otros módulos. En este punto, no creo que sea sensato hacer suposiciones sobre cuántas veces se importará settings.py. En realidad, tales suposiciones no son seguras en general. He tenido este código en lugares que no sean settings.py, y los resultados son similares.

Tienes que codificar esto. Es decir, debe verificar su registrador para los manejadores existentes antes de agregar controladores adicionales a él. Esto es un poco feo porque es perfectamente razonable tener múltiples manejadores, incluso del mismo tipo, conectados a un registrador. Hay algunas soluciones para lidiar con esto. Una de ellas es verificar la propiedad de los manipuladores de su objeto logger. Si solo quieres un manejador y tu longitud> 0, entonces no lo agregues. Personalmente, no me gusta esta solución, porque se complica con más controladores.

Prefiero algo como esto (gracias a Thomas Guettler):

# file logconfig.py if not hasattr(logging, "set_up_done"): logging.set_up_done=False def set_up(myhome): if logging.set_up_done: return # set up your logging here # ... logging.set_up_done=True

Debo decir que me gustaría que el hecho de que Django importase settings.py varias veces estuviera mejor documentado. Y me imagino que mi configuración es de alguna manera causa de esta importación múltiple, pero estoy teniendo problemas para descubrir qué está causando el problema y por qué. Tal vez no pude encontrar eso en sus documentos, pero creo que ese es el tipo de cosas que necesita advertir a sus usuarios.


Puede solucionar su problema comprobando el número de controladores cuando está haciendo su init.

def init_logging(): stdoutHandler = logging.StreamHandler( sys.stdout ) stdoutHandler.setLevel( DEBUG ) stdoutHandler.setFormatter( logging.Formatter( LOG_FORMAT_WITH_TIME ) ) logger = logging.getLogger( LOG_AREA1 ) if len(logger.handlers) < 1: logger.addHandler( stdoutHandler )

No creo que esta sea una excelente forma de manejarlo. Personalmente, para iniciar sesión en django con el módulo de registro de Python, creo un registrador en views.py para cada aplicación que me interesa, luego tomo el registrador en cada función de visualización.

from django.http import HttpResponse from magic import makeLogger from magic import getLogger makeLogger(''myLogName'', ''/path/to/myLogName.log'') def testLogger(request): logger = getLogger(''myLogName'') logger.debug(''this worked'') return HttpResponse(''TEXT, HTML or WHATEVER'')

Este es un artículo bastante bueno sobre la depuración de django y cubre algunos registros: http://simonwillison.net/2008/May/22/debugging/


Revivir un hilo viejo, pero estaba experimentando mensajes duplicados al usar el registro Django 1.3 Python con el formato dictConfig .

El disable_existing_loggers se deshace del problema del disable_existing_loggers / registro duplicado con múltiples cargas de settings.py, pero aún puede obtener mensajes de registro duplicados si no especifica el booleano de propagate apropiada en el logger específico. A saber, asegúrese de establecer propagate=False para los registradores secundarios. P.ej,

''loggers'': { ''django'': { ''handlers'':[''null''], ''propagate'': True, ''level'':''INFO'', }, ''django.request'': { ''handlers'': [''console''], ''level'': ''ERROR'', ''propagate'': False, }, ''project'': { ''handlers'': [''console'', ''project-log-file''], ''level'': ''DEBUG'', ''propagate'': True, }, ''project.customapp'': { ''handlers'': [''console'', ''customapp-log-file''], ''level'': ''DEBUG'', ''propagate'': False, }, }

Aquí, project.customapp establece propagate=False para que el registrador de project tampoco lo capture. Los dev son excelentes, como siempre.


También puede usar un middleware run-once para obtener un efecto similar, sin las variables privadas. Tenga en cuenta que esto solo configurará el registro para las solicitudes web; necesitará encontrar una solución diferente si desea iniciar sesión en su shell o ejecuta el comando.

from django.conf import settings from django.core.exceptions import MiddlewareNotUsed import logging import logging.handlers import logging.config __all__ = (''LoggingConfigMiddleware'',) class LoggingConfigMiddleware: def __init__(self): ''''''Initialise the logging setup from settings, called on first request.'''''' if hasattr(settings, ''LOGGING''): logging.config.dictConfig(settings.LOGGING) elif getattr(settings, ''DEBUG'', False): print ''No logging configured.'' raise MiddlewareNotUsed(''Logging setup only.'')


Una manera de hackear, pero puedes intentar poner el código de registro dentro de un admin.py. Se supone que debe importarse solo una vez.

Alternativamente; ¿Puedes comprobar primero si existe el registro MyApp.views.scans ? Si existe (tal vez se genera un error), simplemente puede omitir la creación (y, por lo tanto, no agregar el controlador de nuevo). Una manera más limpia pero no lo he intentado sin embargo.

También debe haber un lugar más apropiado para poner este código ( __init__.py ?). settings.py es para la configuración.