Python进阶(1)- logging

1. logging日志处理

1.1. logging库日志级别

|----------|----------|---------------------------|
| 级别 | 级别数值 | 使用时机 |
| DEBUG | 10 | 详细信息,常用于调试。 |
| INFO | 20 | 程序正常运行过程中产生的一些信息。 |
| WARNING | 30 | 警告用户,虽然程序还在正常工作,但有可能发生错误。 |
| ERROR | 40 | 由于更严重的问题,程序已不能执行一些功能了。 |
| CRITICAL | 50 | 严重错误,程序已不能继续运行。 |


  1. 默认的日志级别为warning

    import logging

    默认是warning级别的输出

    logging.debug("This is a debug message")
    logging.info("This is an info message")
    logging.warning("This is a warning message")
    logging.error("This is an error message")
    logging.critical("This is a critical message")

  • baseconfig()方法:

(1) 设置日志级别

复制代码
import logging
# 默认是warning级别的输出
# 使用baseconfig()方法设置级别
logging.basicConfig(level=logging.DEBUG)
logging.debug("This is a debug message")
logging.info("This is an info message")
logging.warning("This is a warning message")
logging.error("This is an error message")
logging.critical("This is a critical message")

(2) 将日志保存到文件系统

复制代码
logging.basicConfig(level=logging.DEBUG,filemode='w',filename='debug.log')
  • filemode = 'a':追加
  • filemode = 'w':写入

(3) 向日志输出变量

复制代码
import logging
# 默认是warning级别的输出
# 使用baseconfig()方法设置级别
logging.basicConfig(level=logging.DEBUG,filemode='w',filename='debug.log')
logging.debug("姓名:%s,年龄:%d","张三",18)
logging.debug("姓名:{},年龄:{}".format("张三",18))
logging.debug(f"姓名:{'张三'},年龄:{18}")

1.2. 输出时间

logging 日志专用的格式化语法,和字符串格式化是同一个意思:

  • %(asctime)s → 时间

  • %(levelname)s → 日志级别

  • %(filename)s → 文件名

  • %(lineno)s → 行号

  • %(message)s → 你输出的日志内容

    -- coding: utf-8 --

    import logging

    %()s

    logging.basicConfig(
    format="%(asctime)s|%(levelname)s|%(filename)s|%(lineno)s|%(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
    level=logging.DEBUG # 设置级别
    )

    name = "张三"
    age = 18

    正确:小写 debug

    logging.debug(f"姓名:{name},年龄:{age}")

1.3. 高级应用:Loggers

Loggers:记录器,提供应用程序代码能直接使用的接口

1. 提供应用程序的调用接口

  • 核心代码

    import logging
    logger = logging.getLogger(name)

  • 关键特性

    • logger单例模式:同一个名称的 Logger 在整个程序中只会创建一个实例,避免重复配置和日志重复输出。
    • __name__ 是 Python 内置变量,代表当前模块名,用它命名 Logger 可以精准区分不同模块的日志来源。
  • 使用场景 :在代码中通过 logger.debug()logger.info() 等方法记录日志。

2. 决定日志记录的级别

  • 核心代码

    logger.setLevel(logging.DEBUG)

  • 作用

    • 设置 Logger 的最低日志级别,只有级别≥当前设置的日志才会被处理。
    • 例如设置为 DEBUG 时,DEBUG/INFO/WARNING/ERROR/CRITICAL 级别的日志都会被传递;若设置为 INFO,则 DEBUG 级别的日志会被直接过滤。
  • 优先级:Logger 的级别会优先于 Handler 的级别,是日志过滤的第一道关卡。

3. 将日志内容传递到关联的 Handlers 中

  • 核心代码

    添加处理器

    logger.addHandler(file_handler)
    logger.addHandler(console_handler)

    移除处理器

    logger.removeHandler(console_handler)

  • 作用

    • 通过 addHandler() 绑定一个或多个处理器(Handler),让 Logger 产生的日志可以同时输出到多个目的地(比如控制台 + 文件)。
    • 通过 removeHandler() 可以解绑不再需要的处理器,灵活控制日志输出渠道。
  • 流程:Logger 过滤后的日志,会被分发到所有绑定的 Handlers 中,再由 Handlers 完成最终的输出。

1.4. 高级应用:Handlers

核心作用:负责将记录器产生的日志发送到指定目的地。

1. StreamHandler(流处理器)

  • 核心作用 :将日志输出到标准输出流(stdout,如控制台 / 显示器),适合开发调试时实时查看日志。

  • 创建语法

    import logging
    sh = logging.StreamHandler(stream=None)

    • stream 参数:指定输出流,默认 None 表示使用 sys.stdout(控制台)。
  • 典型场景:开发阶段,快速查看日志输出,不需要持久化到文件。

2. FileHandler(文件处理器)

  • 核心作用 :将日志持久化保存到磁盘文件中,适合生产环境留存日志记录。

  • 创建语法:python运行

    fh = logging.FileHandler(
    filename, # 日志文件名(含路径)
    mode='a', # 文件打开模式:'a'=追加写入,'w'=覆盖写入
    encoding=None,# 文件编码(推荐设为 'utf-8' 避免中文乱码)
    delay=False # 是否延迟打开文件,True 表示第一次 emit 时才打开
    )

  • 关键参数说明

    • mode='a':默认追加模式,不会覆盖之前的日志内容,生产环境推荐使用。
    • encoding='utf-8':必须显式指定,否则中文日志可能出现乱码。

3. setFormatter ():绑定格式化器

  • 核心作用:为 Handler 设置日志的输出格式,决定日志最终的展示结构。

  • 使用示例:python运行

    创建格式化器

    formatter = logging.Formatter("%(asctime)s|%(levelname)s|%(message)s")

    为处理器绑定格式化器

    sh.setFormatter(formatter)
    fh.setFormatter(formatter)

  • 注意:每个 Handler 可以绑定独立的 Formatter,实现 "控制台和文件输出不同格式日志" 的需求。

日志级别 ≥ logger 级别 并且 日志级别 ≥ handler 级别 才会输出

1.5. 高级应用:Formatter

Formatter 是 Python logging 模块中最终决定日志输出结构的组件,负责定义日志的顺序、字段和格式。


1. 构造方法解析

复制代码
ft = logging.Formatter(fmt=None, datefmt=None, style='%')

|-----------|------------------------------------|-----------------------------------------------|
| 参数 | 作用 | 默认值 |
| fmt | 日志格式字符串,定义日志包含的字段(如 %(asctime)s) | None(默认仅输出日志内容) |
| datefmt | 时间字段 %(asctime)s的格式字符串 | %Y-%m-%d %H:%M:%S (如 2026-03-26 15:30:00) |
| style | 格式化语法风格,可选 %/{/$ | % |


2. 关键参数详解

  • datefmt**(时间格式)**
    • 默认格式:%Y-%m-%d %H:%M:%S(年 - 月 - 日 时:分: 秒)

    • 自定义示例:

      时间格式改为:年/月/日 时:分

      formatter = logging.Formatter("%(asctime)s|%(message)s", datefmt="%Y/%m/%d %H:%M")

  • style**(语法风格)**

    • style='%':默认旧式 %() 语法,如 %(asctime)s|%(levelname)s
    • style='{':支持 str.format() 语法,如 {asctime}|{levelname}
    • style='$':支持 string.Template 语法,如 ${asctime}|${levelname}

3. 完整使用示例

复制代码
# -*- coding: utf-8 -*-
import logging

# 1. 创建记录器并设置日志级别
logger = logging.getLogger('applog')
logger.setLevel(logging.DEBUG)

# 2. 控制台处理器
consolehandler = logging.StreamHandler()
consolehandler.setLevel(logging.DEBUG)

# 3. 文件处理器(使用 logger 的级别)
fh = logging.FileHandler(filename='appDemo.log', encoding='utf-8', mode='a')

# 4. 日志格式
formatter = logging.Formatter(
    "%(asctime)s|%(levelname)8s|%(filename)s|%(lineno)s|%(message)s"
)

# 5. 给两个处理器都设置格式 ✅
consolehandler.setFormatter(formatter)  
fh.setFormatter(formatter)

# 6. 把处理器添加到记录器
logger.addHandler(consolehandler)
logger.addHandler(fh)

# ------------------- 正确输出日志 -------------------
# 三种格式化方式都正确
logger.debug("姓名:%s,年龄:%d", "张三", 18)
logger.debug("姓名:{},年龄:{}".format("张三", 18))
logger.debug(f"姓名:{'张三'},年龄:{18}")

1.6. 高级应用:Filters

只有日志来源(logger 名称)以 cn.cccb****开头的日志,才会被输出!不是这个来源的日志,全部被过滤掉,不输出!

复制代码
# 7. 定义一个过滤器
filter = logging.Filter("cn.cccb")
logger.addFilter(filter)

1.7. 高级应用:配置文件

复制代码
#./logging.conf

#记录器:提供应用程序代码直接使用的接口
#设置记录器名称,root必须存在!!!
[loggers]
keys=root,applog

#处理器,将记录器产生的日志发送至目的地
#设置处理器类型
[handlers]
keys=fileHandler,consoleHandler

#格式化器,设置日志内容的组成结构和消息字段
#设置格式化器的种类
[formatters]
keys=simpleFormatter

#设置记录器root的级别与种类
[logger_root]
level=DEBUG
handlers=consoleHandler

#设置记录器applog的级别与种类
[logger_applog]
level=DEBUG
handlers=fileHandler,consoleHandler
#起个对外的名字
qualname=applog
#继承关系
propagate=0

#设置
[handler_consoleHandler]
class=StreamHandler
args=(sys.stdout,)
level=DEBUG
formatter=simpleFormatter

[handler_fileHandler]
class=handlers.TimedRotatingFileHandler
#在午夜1点(3600s)开启下一个log文件,第四个参数0表示保留历史文件
args=('applog.log','midnight',3600,0)
level=DEBUG
formatter=simpleFormatter

[formatter_simpleFormatter]
format=%(asctime)s|%(levelname)8s|%(filename)s[:%(lineno)d]|%(message)s
#设置时间输出格式
datefmt=%Y-%m-%d %H:%M:%S
相关推荐
Kang.Charles2 小时前
python读取环境变量
python
飞翔的烤鸡翅2 小时前
Kilo Code在PyCharm上的一些实践
ide·python·pycharm·ai编程·kilo code
Roselind_Yi2 小时前
从线性回归实战到Python依赖安装踩坑:我的机器学习入门排雷记
笔记·python·算法·机器学习·回归·线性回归·学习方法
干啥啥不行,秃头第一名2 小时前
Python深度学习入门:TensorFlow 2.0/Keras实战
jvm·数据库·python
二闹2 小时前
一文了解Python里的函数名和函数参数到底啥关系?
后端·python
sin°θ_陈2 小时前
前馈式3D Gaussian Splatting 研究地图(路线一):像素对齐高斯的起点——pixelSplat 与 latentSplat 在解决什么
python·深度学习·3d·aigc·webgl·3dgs·空间智能
Bert.Cai2 小时前
Python标识符详解
开发语言·python
Allen_LVyingbo2 小时前
自进化医疗智能体:动态记忆与持续运行的Python架构编程(上)
数据结构·python·架构·动态规划·健康医疗