python logger 打印多次的问题与解决方案

学习 Python 不久碰到过这个问题, 记得当时没查出是什么问题. 刚刚无意中发现了这个问题的原因及解决方案, 记录一下.

参考:
https://juejin.im/post/5bc2bd3a5188255c94465d31

第一种情况

参考文章中介绍说产生这个问题的原因是因为创建了自定义的 Logger 对象后, 又使用了 logging 中的日志输出方法,这些方法使用的是默认配置的 Logger 对象,导致之后输出的日志信息会重复。

示例代码:

import logging

# 日志管理
logger = logging.getLogger('logger')
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
# 输出到控制台的log
sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG)
sh.setFormatter(formatter)
logger.addHandler(sh)

logger.debug('a debug message')
logger.info('a info message')
logger.warning('a warning message')
logging.error('a error message')
logger.critical('a critical message')

打印结果如下:

2019-07-17 09:42:29,336 spider.py[line:92] DEBUG a debug message
2019-07-17 09:42:29,336 spider.py[line:93] INFO a info message
2019-07-17 09:42:29,336 spider.py[line:94] WARNING a warning message
ERROR:root:a error message
2019-07-17 09:42:29,336 spider.py[line:96] CRITICAL a critical message
CRITICAL:logger:a critical message
[Finished in 0.6s]

可以看到从 error message 开始出现格式异常, 之后下一条 message 开始重复打印. 之后每一条 log 都会打印出两次. 去掉使用 logging 的日志输出方法后则打印正常.

第二种情况

封装了 logger 到文件后在其他文件 import 引用这个 logger . 却又在文件中创建了新的 logger . 如下:

封装了 loggerbase_utils:

import configparser
import logging
import time
import os

# 配置文件管理
confLoad = configparser.ConfigParser()
confLoad.read('./spider.conf')

# 日志管理
logger = logging.getLogger('logger')
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
# 输出到log目录下的当日log文件
log_dir = confLoad.get('logger','LOG_DIR')
if not os.path.exists(log_dir):
    os.makedirs(log_dir)
logFile = log_dir + time.strftime("%Y-%m-%d", time.localtime()) + ".log"
fh = logging.FileHandler(logFile, encoding='utf-8')
fh.setLevel(int(confLoad.get('logger','LOGFILE_LEVEL')))
fh.setFormatter(formatter)
# 输出到控制台的log
sh = logging.StreamHandler()
sh.setLevel(int(confLoad.get('logger','CONSOLE_LEVEL')))
sh.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(sh)

配置文件 spider.conf :

# mongodb
[mongodb]
DB_MONGO_HOST=192.168.0.101
DB_MONGO_PORT=27017
DB_MONGO_DATABASE=spider
DB_MONGO_USERNAME=
DB_MONGO_PASSWORD=

[logger]
LOG_DIR = ./log/

# CRITICAL = 50
# FATAL = CRITICAL
# ERROR = 40
# WARNING = 30
# WARN = WARNING
# INFO = 20
# DEBUG = 10
# NOTSET = 0

CONSOLE_LEVEL = 10
LOGFILE_LEVEL = 10

在文件 spider.py 中引用:

from base_utils import logger

if __name__ == "__main__":
	# 如果在此文件中再次创建 logger, 会产生两个 logger 对象, 使 log 打印 2 次
    logger = logging.getLogger('logger')
    logger.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
	sh = logging.StreamHandler()
    sh.setLevel(logging.DEBUG)
    sh.setFormatter(formatter)
    logger.addHandler(sh)

	logger.debug('a debug message')
    logger.info('a info message')
    logger.warning('a warning message')
    logger.error('a error message')
    logger.critical('a critical message')

打印结果如下:

2019-07-17 10:01:21,969 spider.py[line:93] DEBUG a debug message
2019-07-17 10:01:21,969 spider.py[line:93] DEBUG a debug message
2019-07-17 10:01:21,970 spider.py[line:94] INFO a info message
2019-07-17 10:01:21,970 spider.py[line:94] INFO a info message
2019-07-17 10:01:21,970 spider.py[line:95] WARNING a warning message
2019-07-17 10:01:21,970 spider.py[line:95] WARNING a warning message
2019-07-17 10:01:21,971 spider.py[line:96] ERROR a error message
2019-07-17 10:01:21,971 spider.py[line:96] ERROR a error message
2019-07-17 10:01:21,971 spider.py[line:97] CRITICAL a critical message
2019-07-17 10:01:21,971 spider.py[line:97] CRITICAL a critical message
[Finished in 0.6s]

可以看到 log 打印了 2 次, 同样的要避免这样子使用.

<think>首先,用户的问题是关于Python脚本中logger.debug不打印解决方案。用户提供了几个参考资料,我需要参考这些引用,并基于我的知识和这些资料给出解决方案。 关键引用回顾: - 引用[1]: 展示了一些logger的使用例子(info, debug, warning),但不涉及不打印问题。 - 引用[2]: 讨论了Pythonlogger模块,提到logging套件只接收字符串类型的消息。 - 引用[3]: 解释了如何使用logging.debug()替换print(),并提到通过修改level来控制输出。例如,设置level来控制debug信息是否输出。 - 引用[4]: 提到Pythonlogger模块有两种实现方法,第二种更灵活。 - 引用[5]: 解释了basicConfig函数的作用,它配置根日志记录器,只能调用一次,通常放在程序开头。 用户的问题logger.debug不打印,这通常是由于日志级别设置不正确造成的。 常见原因和解决方案: 1. **日志级别设置过高**:如果日志级别设置为INFO或更高,DEBUG信息不会被打印。 - 解决方案:确保日志级别设置为DEBUG。例如,使用`logging.basicConfig(level=logging.DEBUG)`。 2. **没有配置logger的正确处理程序**:如果没有添加处理程序(如StreamHandler或FileHandler),日志可能不会输出。 - 解决方案:添加处理程序并设置级别。 3. **basicConfig调用问题**:如引用[5]所说,basicConfig配置根日志记录器,且只能调用一次。如果在其他地方再次调用,可能会被忽略。 - 解决方案:只在程序开头调用一次basicConfig。 4. **logger对象未设置级别**:如果使用自定义logger,可能需要单独设置级别。 - 解决方案:设置logger的级别为DEBUG,例如`logger.setLevel(logging.DEBUG)`。 5. **处理程序未设置级别**:即使logger级别设置为DEBUG,如果处理程序级别更高,也不会输出。 - 解决方案:确保处理程序也有足够的级别。 基于引用[3]的例子: - 它展示了如何设置level来控制debug输出:`logging.basicConfig(level=logging.DEBUG)` 结构化我的回答: - 解释问题原因。 - 提供逐步解决方案。 - 包括代码示例。 - 参考提供的引用。 回答结构: 1. **引入问题**:简要描述logger.debug不打印的常见原因。 2. **核心解决方案**: - 检查并设置日志级别。 - 确保正确配置处理程序。 - 调用basicConfig一次。 3. **代码示例**:给出一个完整的工作示例。 4. **相关建议**:提示其他可能的问题。 5. **生成相关问题**:如系统指令要求。 确保使用中文,因为系统指令指定了中文回答。 最后,生成相关问题,基于用户查询。 相关问题想法: 1. 如何设置Python日志级别? 2. Python日志模块的常见错误有哪些? 3. 如何将日志输出到文件? 4. Python中如何自定义日志格式? 5. 为什么logger.info打印logger.debug不打印? 引用标识:在回答中引用段落末尾添加引用标识,如引用[3]提到设置level。 完整回答大纲: - 开头:解释问题。 - 解决方案步骤: - 步骤1:确保日志级别设置为DEBUG。 - 步骤2:正确配置处理程序。 - 步骤3:调用basicConfig适时。 - 代码示例。 - 结尾:总结。 - 相关问题。 </think>### Python脚本中logger.debug不打印解决方案Python脚本中,`logger.debug()` 不打印日志的常见原因是日志级别设置不当或配置缺失。Python的`logging`模块默认级别为`WARNING`,这意味着`DEBUG`级别的消息会被忽略[^3][^5]。以下我将基于参考引用和最佳实践,提供逐步解决方案解决方案分为两部分:核心调试步骤和完整代码示例。 #### 核心原因逐步解决方案 当`logger.debug()`不输出时,通常涉及以下问题。请按步骤检查和修复: 1. **日志级别设置过高**: - `logging`模块默认级别是`WARNING`,高于`DEBUG`,因此`logger.debug()`会被过滤掉[^3][^5]。 - 解决方案:显式设置日志级别为`DEBUG`。 - 使用`logging.basicConfig(level=logging.DEBUG)`配置根日志记录器(注意:`basicConfig`只能调用一次,通常放在程序开头)[^5]。 - 对于自定义logger对象,使用`logger.setLevel(logging.DEBUG)`。 2. **缺少处理程序(Handler)配置**: - 即使logger级别正确,如果没有添加处理程序(如输出到控制台或文件),日志也不会显示[^3][^4]。 - 解决方案:添加处理程序并设置其级别。 - 使用`StreamHandler()`输出到控制台。 - 确保处理程序级别也设置为`DEBUG`(否则可能被高级别覆盖)。 3. **`basicConfig`调用不当**: - `logging.basicConfig()`用于配置根日志记录器,但只能生效一次。如果在其他地方重复调用,后续调用会被忽略,导致配置失败[^5]。 - 解决方案:确保在脚本开头只调用一次`basicConfig`。 4. **其他常见问题**: - **logger对象未正确实例化**:如果使用自定义logger(而非根logger),需确保其名称和配置一致。 - **消息格式问题**:`logger.debug()`接收字符串参数;如果传递非字符串对象,需先转换,但这不是不打印的主因[^2]。 - **环境变量或外部配置影响**:检查脚本是否被其他模块修改了日志级别。 #### 完整代码示例 以下是一个工作示例,展示如何正确配置`logger.debug()`输出到控制台。参考引用[3]和[^5],使用`basicConfig`设置级别为`DEBUG`,并添加处理程序以确保输出。 ```python import logging # 步骤1:在程序开头配置根日志记录器,设置级别为DEBUG logging.basicConfig( level=logging.DEBUG, # 核心:设置级别为DEBUG,允许debug消息输出 format='%(levelname)s:%(funcName)s:%(message)s', # 自定义格式,可选 handlers=[logging.StreamHandler()] # 添加StreamHandler输出到控制台 ) # 创建logger对象(可选,如果使用根logger可直接用logging.debug) logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # 冗余设置,确保logger级别匹配 # 测试函数 def test_function(): value = 100 logger.debug(f"调试信息: 值={value}, 类型={type(value)}") # 使用f-string传递消息 logger.info("一般信息") logger.warning("警告信息") if __name__ == '__main__': test_function() ``` 运行此脚本,`logger.debug()`将输出类似: ``` DEBUG:test_function:调试信息: 值=100, 类型=<class 'int'> INFO:test_function:一般信息 WARNING:test_function:警告信息 ``` #### 注意事项 - **验证级别设置**:如果仍不打印,尝试在代码中添加`print(logger.getEffectiveLevel())`检查当前级别(返回数值,如DEBUG=10)[^3]。 - **高级配置**:对于复杂项目,推荐使用配置文件或`logging.config.dictConfig`,避免`basicConfig`限制[^4][^5]。 - **引用说明**:本文解决方案基于用户提供的引用,特别是引用[3]强调了通过设置`level=logging.DEBUG`控制输出[^3],以及引用[5]解释了`basicConfig`的单次调用特性[^5]。 如果问题依未解决,请检查脚本是否被其他模块覆盖配置,或分享更多代码细节以进一步诊断。 ### 相关问题 1. 如何将Python日志输出到文件而非控制台? 2. Python日志模块中有哪些常见的处理程序(Handlers)类型? 3. 为什么logger.info()能打印logger.debug()不能? 4. Python中如何自定义日志格式(Formatter)? 5. 在大型项目中,如何管理多个logger对象的配置?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值