Estoy usando el registro de Python y, por alguna razón, todos mis mensajes aparecen dos veces.
Tengo un módulo para configurar el registro:
# BUG: It's outputting logging messages twice - not sure why - it's not the propagate setting.
def configure_logging(self, logging_file):
self.logger = logging.getLogger("my_logger")
self.logger.setLevel(logging.DEBUG)
self.logger.propagate = 0
# Format for our loglines
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
# Setup console logging
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)
self.logger.addHandler(ch)
# Setup file logging as well
fh = logging.FileHandler(LOG_FILENAME)
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)
self.logger.addHandler(fh)
Más adelante, llamo a este método para configurar el registro:
if __name__ == '__main__':
tom = Boy()
tom.configure_logging(LOG_FILENAME)
tom.buy_ham()
Y luego, dentro de, digamos, el módulo buy_ham, llamaría:
self.logger.info('Successfully able to write to %s' % path)
Y por alguna razón, todos los mensajes aparecen dos veces. Comenté uno de los controladores de transmisión, sigue siendo lo mismo. Un poco extraño, no estoy seguro de por qué sucede esto ... jajaja. Suponiendo que me haya perdido algo obvio.
Saludos, Victor
configure_logging()
que no se llama dos veces (por ejemplo, desde el constructor también)? ¿Se crea solo una instancia de Boy ()?self.logger.handlers = [ch]
lugar resolvería este problema, aunque sería mejor asegurarse de no ejecutar este código dos veces, por ejemplo, usandoif not self.logger
al principio.Respuestas:
Está llamando
configure_logging
dos veces (tal vez en el__init__
método deBoy
):getLogger
devolverá el mismo objeto, peroaddHandler
no verifica si ya se ha agregado un controlador similar al registrador.Intente rastrear llamadas a ese método y eliminar uno de estos. O configure una bandera
logging_initialized
inicializada aFalse
en el__init__
método deBoy
y cambieconfigure_logging
para no hacer nada si lologging_initialized
estáTrue
, y para configurarlaTrue
después de haber inicializado el registrador.Si el programa crea varios
Boy
casos, usted tiene que cambiar la forma de hacer las cosas con un global deconfigure_logging
la función de la adición de los controladores y elBoy.configure_logging
método sólo inicializar elself.logger
atributo.Otra forma de resolver esto es verificando el atributo de manejadores de su registrador:
fuente
logger
variable utilizada no era la instanciada de una de mis clases, sino lalogger
variable presente en la caché de Python3. , y el controlador fue agregado cada 60 segundos por un AppScheduler que configuré. Entonces, estaif not logger.handlers
es una forma bastante inteligente de evitar este tipo de fenómeno. ¡Gracias por la solución, camarada :)!Si está viendo este problema y no está agregando el controlador dos veces, vea la respuesta de abarnert aquí
De los documentos :
Entonces, si desea un controlador personalizado en "prueba", y no desea que sus mensajes también vayan al controlador raíz, la respuesta es simple: desactive su indicador de propagación:
logger.propagate = Falso
fuente
El controlador se agrega cada vez que llama desde el exterior. Intente quitar el controlador después de terminar su trabajo:
fuente
logger.handlers.pop()
en Python 2.7, hace el trucoSoy un novato en Python, pero esto pareció funcionar para mí (Python 2.7)
fuente
En mi caso, lo configuraría
logger.propagate = False
para evitar la doble impresión.En el siguiente código, si lo elimina
logger.propagate = False
, verá una impresión doble.fuente
logger.propagate = False
fue la solución para evitar el doble registro en una aplicación Flask alojada por Waitress, al iniciar sesión en laapp.logger
instancia de Flask .Una llamada a las
logging.debug()
llamadaslogging.basicConfig()
si no hay controladores raíz instalados. Eso me estaba sucediendo en un marco de prueba en el que no podía controlar el orden en que se activaban los casos de prueba. Mi código de inicialización estaba instalando el segundo. El predeterminado usa logging.BASIC_FORMAT que no quería.fuente
Parece que si envía algo al registrador (accidentalmente) y luego lo configura, es demasiado tarde. Por ejemplo, en mi código tenía
Obtendría algo como (ignorando las opciones de formato)
y todo se escribió en stdout dos veces. Creo que esto se debe a que la primera llamada a
logging.warning
crea un nuevo controlador automáticamente y luego agregué explícitamente otro controlador. El problema desapareció cuando eliminé la primeralogging.warning
llamada accidental .fuente
Me estaba dando una situación extraña en la que los registros de la consola se duplicaban, pero los registros de mis archivos no. Después de un montón de excavaciones, lo descubrí.
Tenga en cuenta que los paquetes de terceros pueden registrar registradores. Esto es algo a tener en cuenta (y en algunos casos no se puede prevenir). En muchos casos, el código de terceros comprueba si hay controladores de registro raíz existentes ; y si no lo hay, registran un nuevo controlador de consola.
Mi solución a esto fue registrar mi registrador de consola en el nivel raíz:
fuente