Python中关于logger的使用问题
现在自己在写一个项目,有一个主入口模块和其他的功能模块(每个模块为单独的一个 python 文件),请问一下,有什么方法能把日志打印到同一个文件输出呢?之前只试过对每个 py 文件单独打一个 log,没试过这么多模块来进行输出到一个日志里面,求解答
Python中关于logger的使用问题
5 回复
https://docs.python.org/3/library/logging.html
https://docs.python.org/3/library/logging.handlers.html#filehandler
Python中关于logger的使用问题
Python的logging模块确实有点绕,我来给你讲清楚怎么正确使用。
核心概念:
- Logger - 记录器,你通过它来写日志
- Handler - 处理器,决定日志输出到哪里(控制台、文件等)
- Formatter - 格式化器,决定日志的显示格式
- Filter - 过滤器(可选),用于更精细的控制
- Level - 日志级别:DEBUG < INFO < WARNING < ERROR < CRITICAL
标准用法示例:
import logging
# 1. 创建logger
logger = logging.getLogger(__name__) # 推荐使用模块名
logger.setLevel(logging.DEBUG) # 设置logger的级别
# 2. 创建handler(控制台输出)
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO) # 控制台只显示INFO及以上
# 3. 创建formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
console_handler.setFormatter(formatter)
# 4. 将handler添加到logger
logger.addHandler(console_handler)
# 5. 使用logger
logger.debug('调试信息') # 不会显示,因为控制台handler级别是INFO
logger.info('普通信息')
logger.warning('警告信息')
logger.error('错误信息')
常见坑点:
- 重复日志问题 - 多次调用
getLogger()并添加handler会导致重复输出
# 错误示例
logger = logging.getLogger('my_logger')
logger.addHandler(console_handler)
# ... 其他地方又执行了一次
logger.addHandler(console_handler) # 重复添加!
# 正确做法:检查是否已有handler
if not logger.handlers:
logger.addHandler(console_handler)
- 父子logger继承 - logger有层级关系,子logger默认继承父logger的配置
parent_logger = logging.getLogger('parent')
parent_logger.setLevel(logging.WARNING)
child_logger = logging.getLogger('parent.child')
# child_logger默认继承parent_logger的WARNING级别
- basicConfig的坑 - 只能调用一次,且对root logger生效
import logging
# 这个要放在最前面,且只调用一次
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
实际项目中的推荐配置:
# config.py
import logging
import logging.config
LOGGING_CONFIG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'INFO',
'formatter': 'standard',
'stream': 'ext://sys.stdout',
},
'file': {
'class': 'logging.handlers.RotatingFileHandler',
'level': 'DEBUG',
'formatter': 'standard',
'filename': 'app.log',
'maxBytes': 10485760, # 10MB
'backupCount': 5,
},
},
'loggers': {
'': { # root logger
'handlers': ['console', 'file'],
'level': 'DEBUG',
},
'my_module': {
'handlers': ['file'],
'level': 'INFO',
'propagate': False # 不传递给父logger
}
}
}
# 初始化配置
logging.config.dictConfig(LOGGING_CONFIG)
# 在其他模块中直接使用
# module.py
import logging
logger = logging.getLogger(__name__)
logger.info('This works!')
一句话建议: 用dictConfig配置,每个模块用__name__获取logger,避免直接操作root logger。
初始化 logger 的时候日志文件名指定好呀,可以参考一下这个项目中的这个模块有用到 logging 库,所有的日志都写在同一个文件里面 https://github.com/supersu097/mycrawler/blob/master/core/helper.py
同样有个问题,就是怎么样将项目中的不同级别的日志打到不同的文件中

