Nic*_*ick 6 python logging log-level
在我的程序中,我在开头定义了一个类似于此的记录器:
def start_logger():
fh = logging.handlers.RotatingFileHandler('logger.log',
maxBytes=1000000,
backupCount=100)
fh.setLevel(logging.DEBUG)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
fh_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
#fh_fmt = '%(asctime)s - %(funcName)s - %(levelname)s - %(message)s'
ch_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
#ch_fmt = '%(funcName)s - %(levelname)s - %(message)s'
fh.setFormatter(logging.Formatter(fh_fmt))
ch.setFormatter(logging.Formatter(ch_fmt))
root = logging.getLogger()
root.addHandler(fh)
root.addHandler(ch)
Run Code Online (Sandbox Code Playgroud)
然后我有多个从我的主程序调用的文件.为了使它们正常工作,我需要执行以下操作:
import logging
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log.debug("This debug message is ounly output when I set the level again to debug for this file. Otherwise the the log level for this file is WARNING.")
Run Code Online (Sandbox Code Playgroud)
为什么我导入的所有模块的默认级别都设置为警告.为什么在使用log = logging.getLogger(name)导入root记录器时,必须为每个级别再次设置DEBUG级别?这是在具有不同模块的包中创建日志记录模块的最佳方法,还是有更好的解决方案?
让我们从查看Handler.setLevel的作用开始:
将此处理程序的阈值设置为lvl.记录不如lvl严重的消息将被忽略.创建处理程序时,级别设置为NOTSET(这会导致处理所有消息).
任何不如lvl严重的消息都会被忽略.实际上,将其设置为DEBUG是没有意义的(除非您定义自己的日志级别),因为没有比调试更严重的消息.所以,这意味着处理程序不会忽略任何消息.
setLevel是正确的想法,但你是在错误的对象上调用它.看看Logger.setLevel:
将此记录器的阈值设置为lvl.记录不如lvl严重的消息将被忽略.创建记录器时,级别设置为NOTSET(当记录器是根记录器时会导致处理所有消息,或者当记录器是非root记录器时委托给父级).请注意,根记录器是使用级别WARNING创建的.
术语"委托给父母"意味着如果记录器具有NOTSET级别,则遍历其祖先记录器链,直到找到具有NOTSET以外级别的祖先,或者到达根.
如果发现祖先的级别不是NOTSET,那么祖先的级别将被视为祖先搜索开始的记录器的有效级别,并用于确定如何处理日志记录事件.
你正在创建孩子,但他们都是根记录器的孩子.它们的级别设置为NOTSET,并且它传播到根,其默认值为WARNING.因此,您没有看到任何消息.
TL; DR: 解决方案很简单:在记录器上设置级别,而不是处理程序.以下代码应该满足您的需求:
def start_logger():
fh = logging.handlers.RotatingFileHandler('logger.log',
maxBytes=1000000,
backupCount=100)
ch = logging.StreamHandler(sys.stdout)
fh_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
#fh_fmt = '%(asctime)s - %(funcName)s - %(levelname)s - %(message)s'
ch_fmt = '%(asctime)s %(levelname)8s %(message)s [%(filename)s:%(lineno)d]'
#ch_fmt = '%(funcName)s - %(levelname)s - %(message)s'
fh.setFormatter(logging.Formatter(fh_fmt))
ch.setFormatter(logging.Formatter(ch_fmt))
logging.basicConfig(level=logging.DEBUG)
root = logging.getLogger()
root.addHandler(fh)
root.addHandler(ch)
Run Code Online (Sandbox Code Playgroud)
一旦你这样做,你setLevel在制作孩子时就不需要打电话了.
哦,并回答你的其他问题:这正是你应该使用日志库的方式.(我实际上只是将所有内容记录到根记录器,因为我不需要你开发的那种粒度,但是当你有一个案例时,你就是这样做了.)
编辑:显然,setLevel似乎不适用于根记录器.相反,在访问根记录器之前,您必须设置basicConfig.设置级别logging.basicConfig将满足您的需求(至少,它在我的测试中有效).请注意,这样做与从多个模块进行日志记录中给出的示例相匹配,因此应该解决您的问题.