Python日志模块详解



前言:为什么不用print而要用logging?

日常的开发离不开日志,打印日志可以帮助我们排查问题、熟悉代码框架。打印一条日志,简单的print就行,那为什么还要用logging模块呢?print的确能够打印日志,但是当遇到复杂的工业场景,print就显得力不从心了。

一、logging模块的五大核心优势

1. 分级管理

日志分为五级(DEBUG/INFO/WARNING/ERROR/CRITICAL),可动态控制输出。比如:

  • 开发时开启DEBUG,看到所有细节
  • 上线后只保留WARNING及以上级别,避免日志爆炸

2. 格式定制

自动添加时间、模块名、行号等信息,告别手动拼接字符串的麻烦。

# 示例格式:2023-10-01 12:00:00 - WARNING - main.py (Line 10) - 文件内容为空

3. 多路输出

一条日志可同时输出到控制台、文件、甚至发送邮件给运维人员。想象这样一个场景:将ERROR级日志实时发送到运维群聊,而DEBUG日志持久化到数据库。

4. 异常捕获

无需修改代码,通过配置文件即可调整日志行为,适合微服务环境。

5. 动态控制

无需修改代码,通过logging.config模块或字典配置就能动态调整日志行为。这在微服务架构中尤为重要,可以通过热更新配置实现日志策略切换。

二、logging模块核心组件

1. Logger(记者)

  • 负责收集日志,通过logging.getLogger(name)获取
  • Logger对象是线程安全的,且采用单例模式,因此在程序中可以多次调用getLogger(name)获取同一个Logger实例
  • 不同模块建议用不同名称(如__name__),方便追踪来源

2. Handler(发布渠道)

  • 决定日志发到哪:文件、控制台等。
  • 一个Logger可绑定多个Handler,比如同时输出到文件和邮件

3. Filter(过滤器)

  • 过滤不重要的日志,比如只记录包含特定关键词的ERROR日志
  • 它可以在Logger和Handler级别上设置,用于过滤日志消息

4. Formatter(排版工具)

  • 定义日志格式,可自定义,包括时间、日志级别、日志内容等

三、怎么使用logging模块

1.基础使用:控制台日志

import logging

import logging
logging.debug("this is a debug message.")
logging.info("this is a info message.")
logging.warning("this is a warning message!")
logging.error("this is a error message!")
logging.critical("this is a critical message!")

输出如下:

WARNING:root:this is a warning message!
ERROR:root:this is a error message!
CRITICAL:root:this is a critical message!

为什么debug和info级别的日志都没输出呢?这是因为logging默认的输出级别就是warning,即只输出warning级别或更高级别的日志。

这里,介绍一下日志的分级,按照严重性,由低到高为:

级别使用场景
DEBUG记录详细信息,通常在诊断问题时使用
INFO记录常规信息,确认一切按期进行
WARNING表示发生了意外情况,或在不久的将来会出现某些问题(例如“磁盘空间不足”)。程序仍按预期工作。
ERROR发生了更严重的问题,程序无法执行某些功能
CRITICAL发生了严重错误,程序本身可能无法继续运行

2.将日志写到文件

上面只是在控制台输出日志,在生产开发环境中,往往需要将日志打印到文件中保存起来,以便日后使用。实现如下:

import logging
logger = logging.getLogger(__name__)
logging.basicConfig(filename='test.log', encoding='utf-8', level=logging.INFO)
logger.debug("this is a debug message.")
logger.info("this is a info message.")
logger.warning("this is a warning message!")
logger.error("this is a error message!")
logger.critical("this is a critical message!")

这样,日志就打印到了文件test.log中,如下:

INFO:__main__:this is a info message.
WARNING:__main__:this is a warning message!
ERROR:__main__:this is a error message!
CRITICAL:__main__:this is a critical message!

在上面,第二行创建了一个记录器logger,并直接使用模块的名字作为记录器的名字(在日志中体现为__main__),如果不设置,系统会默认创建名为root的根记录器(在日志中体现为root,如1简单使用中的输出)。

第三行对记录器进行一些基本的配置,设置了日志文件名、编码方式和日志级别,这都是通过logging.basicConfig配置的,其支持的所有配置有:

  • filename:日志文件名
  • filemode:上述文件打开的方式,默认为 ‘a’,表示在文件末尾追加。如需覆盖之前写的,可以使用’w’
  • format:指定日志打印的格式,默认格式为levelname:name:message
  • datefmt:指定日期/时间格式,它使用与 time.strftime() 函数相同的格式化代码
  • style(3.2新增):format字段使用的格式化风格,包括’%‘, ‘{’ or ‘$’,默认使用’%’
  • level:打印日志的最低级别,默认warning
  • stream:用来给StreamHandler初始化,和filename参数不可同时使用
  • handlers(3.3新增):如果指定,需要是创建好的可迭代对象,和filename或stream参数不可同时使用
  • force(3.8新增):
  • encoding(3.9新增):指定编码
  • errors(3.9新增):

下面详细介绍下一些重要的字段

format

它接受一个字符串,其中可以包含各种日志记录的字段占位符,这些占位符会在日志记录时被实际的值替换。常用占位符有:

占位符含义
%(asctime)s日志记录的时间,格式默认为 YYYY-MM-DD HH:MM:SS,sss
%(levelname)s日志级别,如 DEBUG、INFO、WARNING、ERROR、CRITICAL
%(name)s日志记录器的名称
%(message)s日志消息内容
%(filename)s包含日志记录调用的源文件的文件名
%(lineno)s日志记录调用所在的源文件的行号

该字段默认格式为levelname:name:message,比如上面的日志中,

levelname是INFO,name是__main__,message是this is a info message.,这三者之间用冒号分隔

如下,使用上面提到的6个常用占位符,打印一条日志:

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(name)s - %(filename)s - %(lineno)s - %(message)s')
logging.info("this is a info message.")

2025-03-17 15:30:54,006 - INFO - root - test.py - 3 - this is a info message.

style

支持’%', ‘{’ 或 '$'三种风格:

# 使用 % 风格配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', style='%')

# 使用 { 风格配置日志
logging.basicConfig(level=logging.INFO, format='{asctime} - {levelname} - {message}', style='{')

# 使用 $ 风格配置日志
logging.basicConfig(level=logging.INFO, format='$asctime - $levelname - $message', style='$')

3. 记录变量

logging也支持记录变量,支持’%', ‘{’ 或 '$'三种风格格式化的方式

logging.warning('It is %s, %d years old, %.2fm high', 'Tom', 6, 1.2)

WARNING:root:It is Tom, 6 years old, 1.20m high

总结

  • 为什么用logging?:专业分级、灵活输出、规范管理。

  • 核心四件套:Logger(收集)、Handler(输出)、Filter(过滤)、Formatter(排版)。

  • 避坑指南

    • 优先使用Logger对象而非全局的logging.xxx()。

    • 生产环境避免日志文件无限增长(用RotatingFileHandler)。

通过合理配置logging模块,你的程序将拥有清晰的“诊断报告”,问题排查效率提升10倍!

参考链接:

https://docs.python.org/3/howto/logging.html#logging-basic-tutorial

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值