本教程面向需要稳定、可维护日志系统的 Python 开发者,涵盖从基础用法到生产级最佳实践,帮助你快速掌握 logging 的核心概念、配置方式与进阶技巧。
一 基础概念与日志级别
- Logger(记录器):应用代码直接调用的接口,负责产生日志;可通过名称分层(如 a.b 是 a 的子记录器)。
 - Handler(处理器):决定日志去向,如 StreamHandler(控制台)、FileHandler(文件)、以及按大小/时间轮转的 RotatingFileHandler、TimedRotatingFileHandler。
 - Formatter(格式化器):定义日志输出样式,如时间、文件名、行号、级别、消息等。
 - Filter(过滤器):更细粒度的输出控制,可在记录器或处理器上设置。
 - 日志级别(由低到高):DEBUG、INFO、WARNING、ERROR、CRITICAL;默认阈值是 WARNING,只有大于等于该级别的日志才会被输出。
 
二 快速上手与基本配置
- 最简用法(直接使用默认的 root Logger):
 
import logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)
logging.debug("调试信息")
logging.info("程序启动")
logging.warning("磁盘空间偏低")
logging.error("数据库连接失败")
logging.critical("服务不可用")
- 将日志写入文件(覆盖模式):
 
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    filename="app.log",
    filemode="w",  # 'a' 为追加
    datefmt="%Y-%m-%d %H:%M:%S"
)
logging.info("日志已写入文件")
- 说明:
	
- basicConfig 仅在没有处理器附加到 root Logger 时生效,适合做一次性基础配置。
 - 常用格式字段:%(asctime)s、%(name)s、%(levelname)s、%(message)s、%(filename)s、%(lineno)d、%(funcName)s、%(thread)d、%(process)d。
 
 
三 自定义 Logger 与同时输出到控制台和文件
- 推荐做法:为每个模块创建独立的 Logger(名称使用 __name__),并通过多个 Handler 分发到不同目标,且可为不同 Handler 设置不同级别。
 - 示例:控制台输出 INFO 及以上,文件记录 DEBUG 及以上,并包含行号与文件名。
 
import logging
def get_logger(name=__name__, level=logging.DEBUG):
    logger = logging.getLogger(name)
    logger.setLevel(level)
    if logger.handlers:  # 避免重复添加处理器
        return logger
    # 控制台处理器:INFO 及以上
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)
    ch_fmt = logging.Formatter(
        "[%(levelname)-8s] %(name)s:%(lineno)4d | %(message)s"
    )
    ch.setFormatter(ch_fmt)
    # 文件处理器:DEBUG 及以上(自动创建日志文件)
    fh = logging.FileHandler("debug.log", encoding="utf-8")
    fh.setLevel(logging.DEBUG)
    fh_fmt = logging.Formatter(
        "%(asctime)s | %(name)s | %(levelname)-8s | %(filename)s:%(lineno)d | %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S"
    )
    fh.setFormatter(fh_fmt)
    logger.addHandler(ch)
    logger.addHandler(fh)
    logger.propagate = False  # 阻止向父记录器传播,避免重复输出
    return logger
# 使用示例
if __name__ == "__main__":
    log = get_logger()
    log.debug("调试信息,仅写入文件")
    log.info("业务处理开始")
    log.warning("这是一个警告")
    try:
        1 / 0
    except Exception:
        log.exception("发生异常,自动附带堆栈")
- 关键点:
	
- 使用 get_logger(name) 形成层级,便于定位来源模块。
 - 通过 logger.setLevel 与 handler.setLevel 的组合,实现“记录更细、输出更精”的效果。
 - 设置 logger.propagate = False 可避免在多模块场景下出现重复日志。
 
 
四 日志轮转与归档
- 按文件大小轮转(RotatingFileHandler):当日志达到 maxBytes 时滚动,保留 backupCount 个旧文件。
 
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
    "app.log", maxBytes=1024 * 1024, backupCount=5, encoding="utf-8"
)
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter(
    "%(asctime)s | %(levelname)s | %(message)s"
))
logging.getLogger().addHandler(handler)
- 按时间轮转(TimedRotatingFileHandler):可按 S/M/H/D/W0–W6/midnight 等间隔滚动。
 
from logging.handlers import TimedRotatingFileHandler
handler = TimedRotatingFileHandler(
    "app.log", when="midnight", interval=1, backupCount=7, encoding="utf-8"
)
handler.setLevel(logging.INFO)
handler.setFormatter(logging.Formatter(
    "%(asctime)s | %(levelname)s | %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
))
logging.getLogger().addHandler(handler)
- 建议:生产环境务必启用轮转,配合合理的 maxBytes 与 backupCount,避免磁盘被占满。
 
五 多模块项目组织与最佳实践
- 多模块组织(推荐在每个模块中使用 __name__ 获取记录器):
 
# util.py
import logging
log = logging.getLogger(__name__)
def work():
    log.info("工具模块执行中")
# main.py
import logging
import util
log = logging.getLogger(__name__)
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
log.info("主程序启动")
util.work()
log.info("主程序结束")
- 执行顺序与传播:子记录器的日志会向上传播到父记录器;若父子记录器都配置了处理器,可能产生重复输出,可通过 logger.propagate = False 控制。
 - 配置方式选择:
	
- 小项目:使用 basicConfig 或在主模块集中配置。
 - 中大型项目:使用 logging.config.dictConfig 或 YAML 配置文件,便于维护与环境隔离。
 
 - 常见坑与建议:
	
- 避免在库代码中调用 basicConfig(应由应用入口统一配置)。
 - 避免重复添加处理器(可在添加前检查 logger.handlers)。
 - 统一日志格式,包含 时间、模块名、行号、级别,便于检索与定位。
 - 生产环境关闭 DEBUG,或按环境动态调整级别。
 - 敏感信息(如密码、Token)不要写入日志。
 - 异常堆栈使用 logger.exception(...) 自动记录。
 - 多进程场景需使用支持多进程的处理器(如队列处理器或第三方方案)。
 
 
                  
                  
                  
                  
                            
                    
      
          
                
                
                
                
              
                
                
                
                
                
              
                
                
              
            
                  
					17万+
					
被折叠的  条评论
		 为什么被折叠?
		 
		 
		
    
  
    
  
            


            