real practices not logger info error disable_existing_loggers debug best python logging

practices - python logging variables



Cómo usar diferentes formateadores con el mismo controlador de registro en python (2)

¿Es posible iniciar sesión en un solo destino (es decir, usar un FileHandler ) con múltiples registradores (es decir, logging.getLogger("base.foo") y logging.getLogger("base.bar") ), y usar diferentes formateadores para cada uno de los madereros

A mi entender, solo es posible asignar un formateador a cada identificador. ¿Quizás es posible asociar el formateador con un registrador en lugar de con el controlador?


Es fácil enviar a diferentes formateadores basados ​​en record.name . A continuación se muestra el código de ejemplo de prueba de concepto:

import logging class DispatchingFormatter: def __init__(self, formatters, default_formatter): self._formatters = formatters self._default_formatter = default_formatter def format(self, record): formatter = self._formatters.get(record.name, self._default_formatter) return formatter.format(record) handler = logging.StreamHandler() handler.setFormatter(DispatchingFormatter({ ''base.foo'': logging.Formatter(''FOO: %(message)s''), ''base.bar'': logging.Formatter(''BAR: %(message)s''), }, logging.Formatter(''%(message)s''), )) logging.getLogger().addHandler(handler) logging.getLogger(''base.foo'').error(''Log from foo'') logging.getLogger(''base.bar'').error(''Log from bar'') logging.getLogger(''base.baz'').error(''Log from baz'')

Otra forma es abrir el archivo manualmente y crear dos manejadores de flujo desde él con diferentes formateadores.


Pequeño remedio a la excelente solución de Denis.

Sistema de nombres de registro basado en estructura jerárquica:

El name es potencialmente un valor jerárquico separado por foo.bar.baz , como foo.bar.baz (aunque también podría ser simplemente foo , por ejemplo). Los registradores que están más abajo en la lista jerárquica son hijos de los registradores más arriba en la lista. Por ejemplo, dado un registrador con un nombre de foo , los registradores con nombres de foo.bar , foo.bar.baz y foo.bam son todos descendientes de foo .

Por ejemplo, cuando setLevel() para algún registrador, este nivel también se aplicará a registradores secundarios. Es por eso que es posible que desee que su formateador se use para el registrador y también para los registradores secundarios. Por ejemplo, ''one.two'' formateador ''one.two'' también debe aplicarse al registrador ''one.two.three'' (si no hay un formateador para ''one.two.three'' ). Aquí está la versión de DispatchingFormatter que hace el trabajo (código de Python 3):

class DispatchingFormatter: """Dispatch formatter for logger and it''s sub logger.""" def __init__(self, formatters, default_formatter): self._formatters = formatters self._default_formatter = default_formatter def format(self, record): # Search from record''s logger up to it''s parents: logger = logging.getLogger(record.name) while logger: # Check if suitable formatter for current logger exists: if logger.name in self._formatters: formatter = self._formatters[logger.name] break else: logger = logger.parent else: # If no formatter found, just use default: formatter = self._default_formatter return formatter.format(record)

Ejemplo:

handler = logging.StreamHandler() handler.setFormatter(DispatchingFormatter({ ''one'': logging.Formatter(''%(message)s -> one''), ''one.two'': logging.Formatter(''%(message)s -> one.two''), }, logging.Formatter(''%(message)s -> <default>''), )) logging.getLogger().addHandler(handler) print(''Logger used -> formatter used:'') logging.getLogger(''one'').error(''one'') logging.getLogger(''one.two'').error(''one.two'') logging.getLogger(''one.two.three'').error(''one.two.three'') # parent formatter ''one.two'' will be used here logging.getLogger(''other'').error(''other'') # OUTPUT: # Logger used -> formatter used: # one -> one # one.two -> one.two # one.two.three -> one.two # other -> <default>