记录删除/检查/修改由fileConfig()配置的处理程序

Paw*_*iak 50 python logging

如何使用fileConfig()函数删除/检查/修改为记录器配置的处理程序?

要删除有Logger.removeHandler(hdlr)方法,但如果从文件配置处理器,如何首先获取处理程序?

leo*_*luk 55

logger.handlers 包含一个包含记录器所有处理程序的列表.

  • 这没有记录.使用它安全吗? (9认同)
  • @Manish:看看代码,我会说它是安全的,只要你不做多线程.处理程序列表是受Lock保护的共享资源,该列表仅包含对处理程序的引用.如果你做多线程,请不要使用它. (7认同)
  • 值得注意的是,`logger.handlers`不包含从父记录器派生的处理程序.除[RootLogger](http://stackoverflow.com/questions/4150148/logging-hierarchy-vs-root-logger)之外的所有记录器都有其父记录器,它有自己的`handlers`列表. (4认同)
  • 这只包含标准处理程序,如果你自己编写的话怎么办?此外,将其称为列表具有误导性,我正在寻找实例列表,但没有.它只是一个类的集合. (3认同)
  • 注意:“logger.handlers”可能会被“pytest”等包修改(至少如果“logger”是根记录器,即“logger =logging.getLogger()”)。因此,如果您想要可测试的代码(在测试中的行为与在生产中的行为相同),我宁愿避免访问本质上是全局状态的“logger.handlers”。我实在无法理解为什么 Python 开发人员决定通过全局状态来实现日志记录,而不是进行适当的依赖注入。 (2认同)

per*_*ing 5

另一种方法可能是使用 JSON 或 YAML 配置文件,该文件会加载到字典中,然后您可以在将其传递到 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)
Run Code Online (Sandbox Code Playgroud)


Mic*_*ein 5

此代码将打印所有记录器,并为每个记录器处理程序

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] )
Run Code Online (Sandbox Code Playgroud)

这将打印出系统中的记录器和处理程序,包括其状态和级别。

这将帮助您调试日志记录问题

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>
Run Code Online (Sandbox Code Playgroud)

  • 这太神奇了,而且正是我在其他地方找不到的东西。 (3认同)

Ali*_*agg 5

@Mickey-Perlstein 的答案正是我要找的,但清单似乎来自比提供的代码更完整的版本。
这段代码更粗略,但对我的使用和理解至关重要,包括根记录器

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)
Run Code Online (Sandbox Code Playgroud)

输出:

<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)> 
Run Code Online (Sandbox Code Playgroud)