write values modules log getlogger example python logging config

modules - python logging level values



Usando el registro de Python en múltiples módulos (7)

Tengo un pequeño proyecto de pitón que tiene la siguiente estructura:

Project -- pkg01 -- test01.py -- pkg02 -- test02.py -- logging.conf

Planeo usar el módulo de registro predeterminado para imprimir mensajes a stdout y a un archivo de registro. Para usar el módulo de registro, se requiere alguna inicialización:

import logging.config logging.config.fileConfig(''logging.conf'') logger = logging.getLogger(''pyApp'') logger.info(''testing'')

Actualmente, realizo esta inicialización en cada módulo antes de comenzar a registrar mensajes. ¿Es posible realizar esta inicialización solo una vez en un lugar, de manera que se reutilicen las mismas configuraciones registrando todo el proyecto?


¡También podrías pensar en algo como esto!

def get_logger(name=None): default = "__app__" formatter = logging.Formatter(''%(levelname)s: %(asctime)s %(funcName)s(%(lineno)d) -- %(message)s'', datefmt=''%Y-%m-%d %H:%M:%S'') log_map = {"__app__": "app.log", "__basic_log__": "file1.log", "__advance_log__": "file2.log"} if name: logger = logging.getLogger(name) else: logger = logging.getLogger(default) fh = logging.FileHandler(log_map[name]) fh.setFormatter(formatter) logger.addHandler(fh) logger.setLevel(logging.DEBUG) return logger

Ahora podría usar múltiples registradores en el mismo módulo y en todo el proyecto si lo anterior se define en un módulo separado y se importa en otros módulos donde se requiere el inicio de sesión.

a=get_logger("__app___") b=get_logger("__basic_log__") a.info("Starting logging!") b.debug("Debug Mode")


En realidad, cada registrador es hijo del registrador de paquetes del padre (es decir, package.subpackage.module hereda la configuración de package.subpackage) , por lo que todo lo que necesita hacer es simplemente configurar el registrador de raíz. Esto se puede lograr con logging.config.fileConfig (su propia configuración para registradores) o logging.basicConfig (establece el registrador de raíz). Configure el inicio de sesión en su módulo de entrada ( __main__.py o lo que sea que desee ejecutar, por ejemplo, main_script.py . __init__.py funciona)

usando basicConfig:

# package/__main__.py import logging import sys logging.basicConfig(stream=sys.stdout, level=logging.INFO)

usando fileConfig:

# package/__main__.py import logging import logging.config logging.config.fileConfig(''logging.conf'')

y luego crea cada registrador usando:

# package/submodule.py # or # package/subpackage/submodule.py import logging log = logging.getLogger(__name__) log.info("Hello logging!")

Para obtener más información, consulte el Tutorial de registro avanzado .


La mejor práctica es, en cada módulo, tener un registrador definido así:

import logging logger = logging.getLogger(__name__)

cerca de la parte superior del módulo, y luego en otro código en el módulo, por ejemplo

logger.debug(''My message with %s'', ''variable data'')

Si necesita subdividir la actividad de registro dentro de un módulo, use, por ejemplo,

loggerA = logging.getLogger(__name__ + ''.A'') loggerB = logging.getLogger(__name__ + ''.B'')

y log a loggerA y loggerB según corresponda.

En su programa principal o programas, haga, por ejemplo:

def main(): "your program code" if __name__ == ''__main__'': import logging.config logging.config.fileConfig(''/path/to/logging.conf'') main()

o

def main(): import logging.config logging.config.fileConfig(''/path/to/logging.conf'') # your program code if __name__ == ''__main__'': main()

Vea here para el registro desde múltiples módulos, y here para la configuración de registro para el código que se utilizará como un módulo de biblioteca por otro código.

Actualización: Al llamar a fileConfig() , es posible que desee especificar disable_existing_loggers=False si está utilizando Python 2.6 o posterior (consulte los documentos para obtener más información). El valor predeterminado es True para compatibilidad con versiones anteriores, lo que hace que todos los registradores existentes sean deshabilitados por fileConfig() menos que ellos o sus antecesores sean explícitamente nombrados en la configuración. Con el valor establecido en False , los registradores existentes se quedan solos. Si usa Python 2.7 / Python 3.2 o posterior, puede considerar la API dictConfig() que es mejor que fileConfig() ya que le da más control sobre la configuración.


La solución de @ Yarkee parecía mejor. Me gustaría añadir algo más a eso:

class Singleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances.keys(): cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] class LoggerManager(object): __metaclass__ = Singleton _loggers = {} def __init__(self, *args, **kwargs): pass @staticmethod def getLogger(name=None): if not name: logging.basicConfig() return logging.getLogger() elif name not in LoggerManager._loggers.keys(): logging.basicConfig() LoggerManager._loggers[name] = logging.getLogger(str(name)) return LoggerManager._loggers[name] log=LoggerManager().getLogger("Hello") log.setLevel(level=logging.DEBUG)

Entonces LoggerManager puede ser conectable a toda la aplicación. Espero que tenga sentido y valor.


Lanzando en otra solución.

En el init principal de mi módulo, tengo algo como:

import logging def get_module_logger(mod_name): logger = logging.getLogger(mod_name) handler = logging.StreamHandler() formatter = logging.Formatter( ''%(asctime)s %(name)-12s %(levelname)-8s %(message)s'') handler.setFormatter(formatter) logger.addHandler(handler) logger.setLevel(logging.DEBUG) return logger

Luego en cada clase necesito un registrador, lo hago:

from [modname] import get_module_logger logger = get_module_logger(__name__)

Cuando se pierden los registros, puede diferenciar su origen del módulo del que provienen.


Siempre lo hago como abajo.

Use un solo archivo python para configurar mi registro como un patrón singleton que nombre '' log_conf.py ''

#-*-coding:utf-8-*- import logging.config def singleton(cls): instances = {} def get_instance(): if cls not in instances: instances[cls] = cls() return instances[cls] return get_instance() @singleton class Logger(): def __init__(self): logging.config.fileConfig(''logging.conf'') self.logr = logging.getLogger(''root'')

En otro módulo, solo importa la configuración.

from log_conf import Logger Logger.logr.info("Hello")

Este es un patrón singleton para iniciar sesión, de manera simple y eficiente.


Varias de estas respuestas sugieren que en la parte superior de un módulo lo haces

import logging logger = logging.getLogger(__name__)

Entiendo que esto se considera una mala práctica . La razón es que la configuración del archivo desactivará todos los registradores existentes de forma predeterminada. P.ej

#my_module import logging logger = logging.getLogger(__name__) def foo(): logger.info(''Hi, foo'') class Bar(object): def bar(self): logger.info(''Hi, bar'')

Y en tu módulo principal:

#main import logging # load my module - this now configures the logger import my_module # This will now disable the logger in my module by default, [see the docs][1] logging.config.fileConfig(''logging.ini'') my_module.foo() bar = my_module.Bar() bar.bar()

Ahora el registro especificado en logging.ini estará vacío, ya que el registrador existente fue deshabilitado por la llamada fileconfig.

Si bien es posible evitar esto (disable_existing_Loggers = False), de forma realista, muchos clientes de su biblioteca no conocerán este comportamiento y no recibirán sus registros. Facilítelo a sus clientes llamando siempre a logging.getLogger localmente. Sombrero Sugerencia: aprendí sobre este comportamiento del sitio web de Victor Lin .

Entonces, una buena práctica es llamar siempre a logging.getLogger localmente. P.ej

#my_module import logging logger = logging.getLogger(__name__) def foo(): logging.getLogger(__name__).info(''Hi, foo'') class Bar(object): def bar(self): logging.getLogger(__name__).info(''Hi, bar'')

Además, si usa fileconfig en su main, establezca disable_existing_loggers = False, en caso de que los diseñadores de su biblioteca usen instancias de registrador de nivel de módulo.