Pawel Furmaniak
¿Cómo puedo eliminar, inspeccionar y modificar los controladores configurados para mis registradores mediante la función fileConfig()?
Para eliminar, existe el método Logger.removeHandler(hdlr), pero ¿cómo obtengo el controlador en primer lugar si se configuró desde un archivo?
logger.handlers
contiene una lista con todos los controladores de un registrador.
-
Esto no está documentado. ¿Es seguro usarlo?
– Manish
24/04/2012 a las 19:33
-
@Manish: mirando el código, diría que es seguro de usar, siempre que no haga subprocesos múltiples. La lista de controladores es un recurso compartido protegido por un bloqueo y la lista solo contiene referencias a los controladores. No lo use, si hace subprocesos múltiples.
– Enno Groper
9 de febrero de 2013 a las 11:59
-
Esto solo contiene controladores estándar, ¿qué sucede si escribe los suyos propios? Además, llamarlo lista es engañoso, estaba buscando una lista de instancias y no había ninguna. Es solo una colección de clases.
– bartekbrak
22 de marzo de 2017 a las 13:35
-
Vale la pena señalar que
logger.handlers
no incluye controladores derivados del registrador principal. Todos los registradores, excepto RootLogger, tienen su registrador principal que tiene su propiohandlers
lista.– patryk.beza
26 de abril de 2017 a las 20:22
-
Advertencia:
logger.handlers
podría ser modificado por paquetes comopytest
(al menos silogger
es el registrador raíz, es decirlogger = logging.getLogger()
). Entonces, si desea un código comprobable (que se comporte en las pruebas de la misma manera que en producción), prefiero evitar accederlogger.handlers
que es esencialmente un estado global. Realmente me supera por qué los desarrolladores de Python decidieron implementar el registro a través del estado global en lugar de realizar una inyección de dependencia adecuada.– balú
7 dic 2020 a las 20:29
mickey perlstein
Este código imprimirá todos los registradores y para cada registrador sus controladores
for k,v in logging.Logger.manager.loggerDict.items() :
print('+ [%s] {%s} ' % (str.ljust( k, 20) , str(v.__class__)[8:-2]) )
if not isinstance(v, logging.PlaceHolder):
for h in v.handlers:
print(' +++',str(h.__class__)[8:-2] )
Esto imprimirá los registradores y controladores en su sistema, incluidos sus estados y niveles.
Esto lo ayudará a depurar sus problemas de registro
output:
+ [root ] {logging.RootLogger} {DEBUG}
-------------------------
-name=root
-handlers=[<logging.FileHandler object at 0x7fc599585390>, <logging.StreamHandler object at 0x7fc599585550>]
-filters=[]
-propagate=True
-level=10
-disabled=False
-parent=None
+++logging.FileHandler {NOTSET}
-stream=<_io.TextIOWrapper name="/dev/logs/myapp.log" mode="w" encoding='UTF-8'>
-mode=w
-filters=[]
-encoding=None
-baseFilename=/home/dev/logs/myapp.log
-level=0
-lock=<unlocked _thread.RLock object owner=0 count=0 at 0x7fc5a85a4240>
-delay=False
-_name=None
-formatter=<logging.Formatter object at 0x7fc599585358>
+++logging.StreamHandler {DEBUG}
-lock=<unlocked _thread.RLock object owner=0 count=0 at 0x7fc5a85a4210>
-filters=[]
-stream=<ipykernel.iostream.OutStream object at 0x7fc5aa6abb00>
-level=10
-_name=None
-formatter=<logging.Formatter object at 0x7fc5995853c8>
+ [PathFinder ] {logging.Logger} {NOTSET}
-------------------------
-name=PathFinder
-handlers=[]
-filters=[]
-manager=<logging.Manager object at 0x7fc5b09757f0>
-propagate=True
-level=0
-disabled=False
-parent=<logging.RootLogger object at 0x7fc5b09757b8>
-
Esto es increíble y exactamente el tipo de cosas que no pude encontrar en ningún otro lugar.
– Greg Müller
1 de abril de 2019 a las 11:52
-
gracias @GregMueller, estoy trabajando en un módulo auxiliar instalado en pip que ofrecerá otros conocimientos sobre la pila de registro
-Mickey Perlstein
1 de abril de 2019 a las 12:42
-
@jens sí. Hace tiempo que no me comprometo
-Mickey Perlstein
12 de agosto de 2019 a las 23:23
-
Para aquellos que quieren ver el depurador de Mickey en github: github.com/mickeyperlstein/logging_debugger/blob/master/…
– Russau
9 de abril de 2020 a las 14:28
Alias_Knagg
La respuesta de Mickey-Perlstein fue justo lo que estaba buscando, pero la lista parece provenir de una versión mucho más completa que el código proporcionado.
Este código es un poco más tosco, pero crucialmente para mi uso y comprensión, incluye el registrador raíz.
import logging
def listloggers():
rootlogger = logging.getLogger()
print(rootlogger)
for h in rootlogger.handlers:
print(' %s' % h)
for nm, lgr in logging.Logger.manager.loggerDict.items():
print('+ [%-20s] %s ' % (nm, lgr))
if not isinstance(lgr, logging.PlaceHolder):
for h in lgr.handlers:
print(' %s' % h)
Producción:
<RootLogger root (DEBUG)>
<TimedRotatingFileHandler /path/to/myapp.log (DEBUG)>
<StreamHandler <stdout> (DEBUG)>
+ [concurrent.futures ] <Logger concurrent.futures (DEBUG)>
+ [concurrent ] <logging.PlaceHolder object at 0x7f72f624eba8>
+ [asyncio ] <Logger asyncio (DEBUG)>
+ [myapp ] <Logger myapp (DEBUG)>
+ [flask.app ] <Logger flask.app (DEBUG)>
+ [flask ] <Logger flask (DEBUG)>
+ [werkzeug ] <Logger werkzeug (ERROR)>
-
Me gustan tus detalles concisos, gran “tenedor”
-Mickey Perlstein
18 de junio de 2020 a las 13:24
-
Esto también enumeró el FileHandler que definí en un archivo de configuración en RootLogger (el código de Mickey no).
– Roberto
4 de junio de 2021 a las 11:05
Otro enfoque podría ser usar un archivo de configuración JSON o YAML que se carga en un diccionario que luego puede ver/manipular antes de pasarlo a logger.config.
import yaml
import logging.config
with open (LOG_CONFIG, 'rt') as f:
config=yaml.safe_load(f)
config['handlers']['error_file_handler']['filename']='foo'
logging.config.dictConfig(config)
sicro
Volver a eliminar controladores: si ayuda a alguien, quería eliminar todos los controladores para todos los registros que había creado (estaba aprendiendo sobre el registro de Python) y se me ocurrió esto:
def log_close():
# Get all loggers
loggers = [logging.getLogger(name) if 'your_app_name' in name else None for name in logging.root.manager.loggerDict]
# For each valid logger remove all handlers
for log in loggers:
if log != None:
while bool(len(log.handlers)):
for handler in log.handlers:
log.removeHandler(handler)
# Set up log
log = logging.getLogger('your_app_name')
log.setLevel('DEBUG')
log_format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
date_format="%Y-%m-%d %H:%M:%S"
formatter = logging.Formatter(log_format, date_format)
log_filename="your_app_name.log"
log_write_mode="w+"
file_handler = logging.FileHandler(log_filename, log_write_mode)
file_handler.setFormatter(formatter)
log.addHandler(file_handler)
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
log.addHandler(console_handler)