当前位置: 首页 > news >正文

python中的logging库详细解析

目录

1. 前言

2. 基础使用

2.1 简单日志记录

2.2 日志级别

3.  高级功能

3.1 日志格式化

3.2 文件日志

3.3 多模块日志

3.4 日志处理器和过滤器

3.5 多处理器日志记录案例

3.6 使用LogRecord对象

3.7 日志传播

3.8 日志旋转和归档

3.9 JSON格式日志

3.10  异步日志记录

4. 总结


1. 前言

在开发复杂的Python应用程序时,调试和监控程序运行状态是必不可少的。Python的logging库提供了一种灵活且强大的机制来记录程序运行时的信息。与简单的print语句相比,logging库提供了更多的功能和更好的组织方式,适合从简单的脚本到大型应用的各种场景。

本文将详细介绍Python中logging库的使用方法,通过实例代码帮助读者深入理解如何有效地利用这个库进行日志记录。

2. 基础使用

2.1 简单日志记录

最简单的日志记录可以通过logging模块的基本配置来实现:

import logging# 配置日志基础设置
logging.basicConfig(level=logging.DEBUG,format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 记录不同级别的日志
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.2 日志级别

logging库定义了5个日志级别,从低到高依次是:

  • DEBUG:详细的信息,通常只在诊断问题时使用。

  • INFO:确认程序按预期运行。

  • WARNING:表明有意外发生,或可能存在潜在的问题。

  • ERROR:由于更严重的问题导致程序的某些功能不能正常执行。

  • CRITICAL:严重的错误,表明程序可能无法继续运行。

日志级别可以通过basicConfiglevel参数进行设置,只有高于或等于该级别的日志才会被输出。

3.  高级功能

3.1 日志格式化

我们可以自定义日志的输出格式,包括时间戳、日志级别和消息内容等:

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',datefmt='%Y-%m-%d %H:%M:%S')logging.warning('This is a formatted warning message')

3.2 文件日志

除了将日志输出到控制台,我们还可以将日志记录到文件:

logging.basicConfig(filename='app.log',filemode='w',level=logging.DEBUG,format='%(name)s - %(levelname)s - %(message)s')logging.info('This message will be written to app.log')

3.3 多模块日志

在多模块项目中,通常需要在不同模块中使用相同的日志配置:

# main.py
import logging
import modulelogger = logging.getLogger(__name__)if __name__ == "__main__":logging.basicConfig(level=logging.DEBUG)logger.info('This is from main module')module.do_something()
# module.py
import logginglogger = logging.getLogger(__name__)def do_something():logger.info('Doing something in module')
  • 每个模块使用自己的日志记录器名称,便于区分不同模块的日志输出。

  • 在大型项目中,这种做法有助于追踪日志的来源。

3.4 日志处理器和过滤器

logging库允许我们添加多个处理器和过滤器来自定义日志行为:

import logging# 创建logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)# 创建控制台处理器和文件处理器
console_handler = logging.StreamHandler()
file_handler = logging.FileHandler('app.log')# 设置日志级别
console_handler.setLevel(logging.WARNING)
file_handler.setLevel(logging.DEBUG)# 创建formatter并添加到处理器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)# 将处理器添加到logger
logger.addHandler(console_handler)
logger.addHandler(file_handler)# 记录日志
logger.debug('This is a debug message')  # 仅写入文件
logger.info('This is an info message')   # 仅写入文件
logger.warning('This is a warning message')  # 写入文件和控制台

3.5 多处理器日志记录案例

在实际应用中,我们可能需要将不同级别的日志记录到不同的地方:

import logging
import sys# 创建一个logger
logger = logging.getLogger('my_logger')
logger.setLevel(logging.DEBUG)# 创建控制台处理器,只记录WARNING及以上级别的日志
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.WARNING)
console_formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(console_formatter)# 创建文件处理器,记录所有DEBUG及以上级别的日志
file_handler = logging.FileHandler('debug.log')
file_handler.setLevel(logging.DEBUG)
file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(file_formatter)# 添加处理器到logger
logger.addHandler(console_handler)
logger.addHandler(file_handler)# 记录不同级别的日志
logger.debug('This is a debug message')      # 仅写入文件
logger.info('This is an info message')       # 仅写入文件
logger.warning('This is a warning message')  # 写入文件和控制台
logger.error('This is an error message')     # 写入文件和控制台

3.6 使用LogRecord对象

在更高级的用法中,我们可以直接创建LogRecord对象:

import logginglogger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG)record = logger.makeRecord('my_logger', logging.WARNING, 'my_module.py', 10, 'This is a custom log record', args=None, exc_info=None)logger.handle(record)
  1. makeRecord的作用

    • 用于手动创建一个LogRecord对象。

    • 适合在需要更灵活控制日志记录的场景下使用,例如在测试中或需要动态生成日志消息时。

  2. LogRecord对象

    • 这个对象包含了日志记录的所有信息,包括时间戳、日志级别、消息内容等。

    • 处理器(如StreamHandlerFileHandler)使用这个对象来决定如何输出日志。

3.7 日志传播

子logger会将其日志传播到父logger的处理器,我们可以通过propagate属性来控制这个行为:

import logging# 配置根logger
root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter('%(name)s - %(message)s'))
root_logger.addHandler(handler)# 创建子logger
child_logger = logging.getLogger('child')
child_logger.setLevel(logging.DEBUG)# 阻止日志传播到父logger
child_logger.propagate = False# 为子logger添加自己的处理器
child_handler = logging.FileHandler('child.log')
child_handler.setFormatter(logging.Formatter('%(name)s - %(message)s'))
child_logger.addHandler(child_handler)# 记录日志
child_logger.info('This message will be written to child.log but not to the console')
  • 可以任意指定名称logging.getLogger('child') 中的 'child' 可以替换为你想要的任何名称。

  • 名称的层次结构:通过使用点分名称(如 'child.subchild'),可以创建具有层次关系的日志记录器。

  • 如果你创建了一个名为 'child.subchild' 的日志记录器,它会自动继承 'child' 日志记录器的配置(如日志级别、处理器等),除非你明确地为 'child.subchild' 设置了不同的配置。

3.8 日志旋转和归档

对于长期运行的应用,日志文件可能会变得非常大。我们可以使用RotatingFileHandlerTimedRotatingFileHandler来管理日志文件的大小和生命周期:

import logging
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler# 按文件大小轮转
handler = RotatingFileHandler('app.log', maxBytes=2000, backupCount=5)
logger = logging.getLogger('size_rotator')
logger.setLevel(logging.INFO)
logger.addHandler(handler)
logger.info('This is a log message')# 按时间轮转
handler = TimedRotatingFileHandler('timed_app.log', when='midnight', interval=1)
logger = logging.getLogger('time_rotator')
logger.setLevel(logging.INFO)
logger.addHandler(handler)
logger.info('This is another log message')
  1. when='midnight'

    • 含义:指定日志轮转的时间单位。

    • 可选值

      • 'S':秒

      • 'M':分钟

      • 'H':小时

      • 'D':天

      • 'midnight':每天午夜

      • 'W0''W6':每周的某一天(0 代表周一,6 代表周日)

    • 作用:在这里,'midnight' 表示每天午夜时分轮转日志文件。

2. interval=1

  • 含义:指定轮转的时间间隔。

3.9 JSON格式日志

在现代微服务架构中,JSON格式的日志更便于集中管理和分析:

import logging
import json
from pythonjsonlogger import jsonloggerlogger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)handler = logging.StreamHandler()
formatter = jsonlogger.JsonFormatter('%(asctime)s %(name)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)logger.info('This is a JSON formatted log message', extra={'user': 'john_doe', 'status': 'success'})

3.10  异步日志记录

在高并发场景下,我们可能需要使用异步日志记录来避免阻塞主线程:

import logging
import queue
from logging.handlers import QueueHandler, QueueListener# 创建队列和处理器
log_queue = queue.Queue()
queue_handler = QueueHandler(log_queue)
queue_listener = QueueListener(log_queue, logging.FileHandler('async.log'))# 配置logger
logger = logging.getLogger('async_logger')
logger.setLevel(logging.DEBUG)
logger.addHandler(queue_handler)# 启动监听器
queue_listener.start()try:logger.info('This is an asynchronous log message')
finally:queue_listener.stop()
  • log_queue = queue.Queue()

    • 创建一个队列对象,用于在日志记录器和处理器之间传递日志记录。

  • queue_handler = QueueHandler(log_queue)

    • 创建一个 QueueHandler 对象,用于将日志记录发送到队列中。

  • queue_listener = QueueListener(log_queue, logging.FileHandler('async.log'))

    • 创建一个 QueueListener 对象,用于从队列中读取日志记录,并将其传递给实际的日志处理器(这里是 FileHandler)。

    • FileHandler('async.log') 表示日志将被写入到 async.log 文件中。

4. 总结

Python的logging库是一个功能强大且灵活的日志记录工具,适用于各种规模的应用程序。通过本文的介绍和示例代码,我们学习了:

  1. 基本的日志记录和配置方法

  2. 如何设置日志级别和格式

  3. 如何将日志记录到文件和控制台

  4. 在多模块项目中共享日志配置

  5. 使用处理器和过滤器自定义日志行为

  6. 高级日志管理技巧,包括日志轮转、JSON格式日志和异步日志记录

在实际开发中,合理配置和使用logging库可以帮助我们更好地调试程序、监控系统状态并进行问题排查。对于初学者而言,从简单的basicConfig开始,逐步掌握更高级的功能;对于有经验的开发者,则可以利用logging库的灵活性来满足复杂的日志需求。良好的日志实践是构建健壮、可维护软件系统的重要组成部分!我是橙色小博,关注我,一起在人工智能领域学习进步!

相关文章:

  • AI超级智能体教程(三)---程序调用AI大模型的四种方式(SpringAI+LangChain4j+SDK+HTTP)
  • 二项式分布html实验
  • Low Poly 风格 | 飞机飞行可视化系统
  • 【计算机视觉】CV实战- 深入解析基于HOG+SVM的行人检测系统:Pedestrian Detection
  • 深入解析Mlivus Cloud核心架构:rootcoord组件的最佳实践与调优指南
  • 防火墙技术深度解析:从包过滤到云原生防火墙的部署与实战
  • 软测面经(私)
  • API/SDK
  • 【金仓数据库征文】金仓数据库:开启未来技术脑洞,探索数据库无限可能
  • 【基于Qt的QQMusic项目演示第一章】从界面交互到核心功能实现
  • 基于HTML+CSS实现的动态导航引导页技术解析
  • 数字孪生:从概念到实践,重构未来产业的“虚拟镜像”
  • Java实现背景图片加自适应水印图片
  • Android 编译问题 prebuilts/clang/host/linux-x86
  • Node.js 包管理工具介绍
  • 彻底卸载Python
  • 深入了解Activiti工作流引擎:从基础到实战
  • github把自己的jar包发送到maven中央仓库
  • 技术书籍推荐(003)
  • 用node打开一个网页
  • 一图读懂|上海海关公布一季度数据:钢材出口增长超143%
  • 青海一只人工繁育秃鹫雏鸟破壳后脱险成活,有望填补国内空白
  • “茉上茶田”傍大牌诱导加盟续:违规从事特许经营被罚没670余万元
  • 李公明︱一周书记:大学的价值、韧性以及……不相称的对抗
  • 厚植民营企业家成长土壤是民营经济高质量发展的关键
  • 北大强基计划招生简章发布,笔试部分考试科目有变化