Tengo un pequeño proyecto de Python 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 en stdout y un archivo de registro. Para usar el módulo de registro, se requiere algo de 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 modo que la misma configuración se reutilice al iniciar sesión en todo el proyecto?
fileConfig
a todos los módulos que registran, a menos que tengaif __name__ == '__main__'
lógica en todos ellos. La respuesta de prost no es una buena práctica si el paquete es una biblioteca, aunque podría funcionar para usted: no debe configurar el inicio de sesión en los paquetes de la biblioteca, aparte de agregar aNullHandler
.package/__init__.py
. Ese no es normalmente el lugar donde pones elif __name__ == '__main__'
código. Además, el ejemplo de prost parece que llamará al código de configuración incondicionalmente en la importación, lo que no me parece correcto. En general, el código de configuración de registro debe hacerse en un lugar y no debe ocurrir como un efecto secundario de la importación, excepto cuando está importando __main__.if __name__ == '__main__'
? (no se menciona explícitamente en cuestión si este es el caso)Respuestas:
La mejor práctica es, en cada módulo, tener un registrador definido de esta manera:
cerca de la parte superior del módulo, y luego en otro código del módulo, p. ej.
Si necesita subdividir la actividad de registro dentro de un módulo, use p. Ej.
e inicie sesión en
loggerA
yloggerB
según corresponda.En su programa o programas principales, por ejemplo:
o
Vea aquí para iniciar sesión desde múltiples módulos, y aquí para registrar la configuración del código que otro código utilizará como módulo de biblioteca.
Actualización: al llamar
fileConfig()
, es posible que desee especificardisable_existing_loggers=False
si está utilizando Python 2.6 o posterior (consulte los documentos para obtener más información). El valor predeterminado esTrue
para la compatibilidad con versiones anteriores, lo que hace que todos los registradores existentes se deshabiliten afileConfig()
menos que ellos o sus antepasados se mencionen explícitamente en la configuración. Con el valor establecido enFalse
, los registradores existentes se dejan solos. Si usa Python 2.7 / Python 3.2 o posterior, es posible que desee considerar ladictConfig()
API, que es mejor quefileConfig()
ya que le da más control sobre la configuración.fuente
disable_existing_loggers
bandera que estáTrue
por defecto pero se puede establecer enFalse
.En realidad, cada registrador es un elemento secundario del registrador de paquetes del padre (es decir,
package.subpackage.module
hereda la configuraciónpackage.subpackage)
, por lo que todo lo que necesita hacer es configurar el registrador raíz. Esto puede lograrse mediantelogging.config.fileConfig
(su propia configuración para registradores) ologging.basicConfig
(establece el registrador raíz) Configurar el registro en su módulo de entrada (__main__.py
o lo que quiera ejecutar, por ejemplomain_script.py
.__init__.py
También funciona)usando basicConfig:
usando fileConfig:
y luego crea cada registrador usando:
Para obtener más información, consulte Tutorial avanzado de registro .
fuente
__main__.py
(por ejemplo, si quiero usar el módulo en un script que no tiene registrador), ¿logging.getLogger(__name__)
seguirá haciendo algún tipo de registro en el módulo o generará una excepción?Siempre lo hago como a continuación.
Usar un solo archivo de Python para configurar mi registro como patrón singleton que se llama '
log_conf.py
'En otro módulo, solo importa la configuración.
Este es un patrón singleton para registrar, simple y eficientemente.
fuente
Varias de estas respuestas sugieren que en la parte superior de un módulo usted lo hace
Tengo entendido que esto se considera una muy mala práctica . La razón es que la configuración del archivo deshabilitará todos los registradores existentes de forma predeterminada. P.ej
Y en tu módulo principal:
Ahora el registro especificado en logging.ini estará vacío, ya que el registro existente fue deshabilitado por la llamada fileconfig.
Si bien es posible evitar esto (disable_existing_Loggers = False), de manera realista, muchos clientes de su biblioteca no conocerán este comportamiento y no recibirán sus registros. Facilite a sus clientes siempre llamando a logging.getLogger localmente. Sugerencia: aprendí sobre este comportamiento en el sitio web de Victor Lin .
Por lo tanto, una buena práctica es llamar siempre a logging.getLogger localmente. P.ej
Además, si usa fileconfig en su main, configure disable_existing_loggers = False, en caso de que los diseñadores de su biblioteca usen instancias de registrador a nivel de módulo.
fuente
logging.config.fileConfig('logging.ini')
antesimport my_module
? Como se sugiere en esta respuesta .logger = logging.getLogger(__name__)
'Para mí, una forma simple de usar una instancia de la biblioteca de registro en varios módulos fue la siguiente solución:
base_logger.py
Otros archivos
fuente
Tirando en otra solución.
En init .py de mi módulo tengo algo como:
Luego, en cada módulo necesito un registrador, hago:
Cuando se pierden los registros, puede diferenciar su fuente por el módulo del que provienen.
fuente
¡También podrías pensar en algo como esto!
Ahora podría usar varios registradores en el mismo módulo y en todo el proyecto si lo anterior se define en un módulo separado e importado en otros módulos donde se requiere el registro.
fuente
La solución de @ Yarkee parecía mejor. Me gustaría agregarle algo más:
Por lo tanto, LoggerManager puede conectarse a toda la aplicación. Espero que tenga sentido y valor.
fuente
Hay varias respuestas Terminé con una solución similar pero diferente que tiene sentido para mí, tal vez también tenga sentido para usted. Mi objetivo principal era poder pasar los registros a los controladores por su nivel (registros de nivel de depuración a la consola, advertencias y más arriba a los archivos):
creó un buen archivo util llamado logger.py:
el flask.app es un valor codificado en el matraz. el registrador de aplicaciones siempre comienza con flask.app como nombre del módulo.
ahora, en cada módulo, puedo usarlo en el siguiente modo:
Esto creará un nuevo registro para "app.flask.MODULE_NAME" con el mínimo esfuerzo.
fuente
La mejor práctica sería crear un módulo por separado que tenga un solo método cuya tarea sea asignar un controlador de registro al método de llamada. Guarde este archivo como m_logger.py
Ahora llame al método getlogger () siempre que se necesite el controlador del registrador.
fuente
--debug
opción en la aplicación y desea establecer el nivel de registro en todos los registradores de su aplicación en función de este parámetro ...get_logger(level=logging.INFO)
para devolver algún tipo de singleton, por lo que cuando llamó por primera vez desde la aplicación principal, inicializa el registrador y los controladores con el nivel adecuado y luego devuelve el mismologger
objeto a todos los demás métodos.Nuevo en Python, así que no sé si esto es aconsejable, pero funciona muy bien para no volver a escribir repetitivo.
Su proyecto debe tener un init .py para que pueda cargarse como un módulo
sys._getframe(1)
sugerencia proviene de aquíLuego, para usar su registrador en cualquier otro archivo:
Advertencias:
import [your module]
no funcionará:python -m [your module name].[your filename without .py]
__main__
, pero cualquier solución que use__name__
tendrá ese problema.fuente