Estoy usando Python Logger. El siguiente es mi código:
import os
import time
import datetime
import logging
class Logger :
def myLogger(self):
logger = logging.getLogger('ProvisioningPython')
logger.setLevel(logging.DEBUG)
now = datetime.datetime.now()
handler=logging.FileHandler('/root/credentials/Logs/ProvisioningPython'+ now.strftime("%Y-%m-%d") +'.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
El problema que tengo es que obtengo varias entradas en el archivo de registro para cada logger.info
llamada. ¿Como puedo resolver esto?
Respuestas:
El
logging.getLogger()
ya es singleton. ( Documentación )El problema es que cada vez que llama
myLogger()
, se agrega otro controlador a la instancia, lo que genera registros duplicados.¿Quizás algo como esto?
fuente
loggers.update(dict(name=logger))
? no esloggers[name] = logger
más simple?loggers.update(dict(name=logger))
creará un diccionario con una sola clave llamadaname
y actualizará continuamente esa misma clave. Me sorprende que nadie no haya mencionado esto anteriormente ya que este código está bastante roto :) Hará las modificaciones necesarias.loggers
redundante el diccionario globallogging.getLogger
? ya que realmente solo desea evitar agregar controladores adicionales, parece que prefiere las respuestas a continuación que verifiquen los controladores directamenteDesde Python 3.2, puede verificar si los controladores ya están presentes y, de ser así, borrarlos antes de agregar nuevos controladores. Esto es bastante conveniente al depurar y el código incluye la inicialización de su registrador
fuente
me hizo el truco
usando python 2.7
fuente
Ya usé el
logger
como Singleton y lo verifiquéif not len(logger.handlers)
, pero aún obtuve duplicados : era la salida formateada, seguida de la sin formato.Solución en mi caso:
logger.propagate = False
Créditos a esta respuesta y a los documentos .
fuente
Estás llamando
Logger.myLogger()
más de una vez. Almacenar la instancia registrador vuelve en algún lugar y volver a utilizar que .También tenga en cuenta que si inicia sesión antes de agregar cualquier controlador,
StreamHandler(sys.stderr)
se creará un controlador predeterminado .fuente
Esta es una adición a la respuesta de @ rm957377 pero con una explicación de por qué sucede esto . Cuando ejecuta una función lambda en AWS, llaman a su función desde dentro de una instancia de envoltura que permanece activa para múltiples llamadas. Es decir, si llama
addHandler()
dentro del código de su función, continuará agregando controladores duplicados al singleton de registro cada vez que se ejecute la función. El singleton de registro persiste a través de múltiples llamadas de su función lambda.Para resolver esto, puede borrar sus controladores antes de configurarlos a través de:
fuente
.info()
llamada que no entiendo.Su registrador debería funcionar como singleton. No deberías crearlo más de una vez. A continuación se muestra un ejemplo de cómo podría verse:
fuente
La implementación de logger ya es un singleton.
Fuente: uso de registro en varios módulos
Entonces, la forma en que debe utilizar esto es:
Supongamos que hemos creado y configurado un registrador llamado 'main_logger' en el módulo principal (que simplemente configura el registrador, no devuelve nada).
Ahora en un submódulo, si creamos un registrador secundario siguiendo la jerarquía de nombres 'main_logger.sub_module_logger' , no necesitamos configurarlo en el submódulo. Basta con la creación del registrador siguiendo la jerarquía de nombres.
Y tampoco agregará un controlador duplicado.
Consulte esta pregunta para obtener una respuesta un poco más detallada.
fuente
logger = logging.getLogger('my_logger') ; logger.handlers = [logger.handlers[0], ]
La salida del registrador doble (o triple o ..- según el número de recargas) también puede ocurrir cuando recarga su módulo a través de
importlib.reload
(por la misma razón que se explica en la respuesta aceptada). Estoy agregando esta respuesta solo para una referencia futura, ya que me tomó un tiempo descubrir por qué mi salida está duplicada (triple).fuente
Una solución simple es como
De esta forma, evita agregar un nuevo controlador a los "controladores" de la lista subyacente.
fuente
En pocas palabras, para la mayoría de los casos cuando esto sucede, solo es necesario llamar a logger.getLogger () solo una vez por módulo. Si tiene varias clases como yo, podría llamarlo así:
Ambos tendrán su propio nombre de paquete completo y método donde se registren.
fuente
Puede obtener una lista de todos los controladores para el registrador en particular, por lo que puede hacer algo como esto
En el ejemplo anterior, verificamos si el controlador de un archivo especificado ya está conectado al registrador, pero tener acceso a la lista de todos los controladores le permite decidir qué criterios debe agregar o no a otro controlador.
fuente
Tuve este problema hoy. Dado que mis funciones eran @staticmethod, las sugerencias anteriores se resolvieron con random ().
Mirando algo como:
fuente
fuente