【python】Python中的日志模块logging使用技巧与应用实战

2024-08-21 05:52

本文主要是介绍【python】Python中的日志模块logging使用技巧与应用实战,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏:python综合应用,基础语法到高阶实战教学
景天的主页:景天科技苑

在这里插入图片描述

文章目录

  • Python中日志模块logging
    • 一、日志模块基础
      • 1.1 导入日志模块
      • 1.2 配置日志
      • 1.3 记录日志
      • 1.4 示例代码
    • 二、日志模块的高级特性
      • 2.1 Logger对象
      • 2.2 Handler对象
      • 2.3 Formatter对象
      • 2.4 示例代码:日志输出到文件
      • 2.5 日志级别和过滤器
      • 2.6 日志轮转
      • 2.7 日志配置文件
      • 2.8 示例代码:使用配置文件
      • 注意事项
      • 日志的其他一些高级用法
        • 1. 日志上下文(Context)
        • 2. 异步日志
        • 3. 日志监控和警报
        • 4. 日志的归档和清理
        • 5. 安全性考虑

Python中日志模块logging

在Python开发中,日志记录是一个非常重要的环节。它不仅有助于开发者追踪程序的执行流程,还能在出现问题时提供关键信息,帮助快速定位并解决问题。Python标准库中的logging模块提供了灵活且强大的日志记录功能,支持将日志输出到不同的目标(如文件、终端等),并支持不同级别的日志记录(如调试、信息、警告、错误等)。本文将结合实际案例,详细介绍logging模块的基础用法和高级特性。

一、日志模块基础

1.1 导入日志模块

首先,我们需要导入logging模块。这是使用日志功能的前提。

import logging

1.2 配置日志

在使用logging模块之前,我们可以配置日志的基本设置,如设置日志级别、输出格式等。以下是一个简单的配置示例:

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
  • level: 设置日志级别,可以选择DEBUGINFOWARNINGERRORCRITICAL
  • format: 设置日志输出格式,上述格式中包含了时间、级别和消息。

1.3 记录日志

配置好日志后,我们就可以使用logging模块记录日志了。例如:

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")

1.4 示例代码

下面是一个结合上述内容的示例代码,演示如何在代码中使用logging模块:

import logging# 配置日志
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')def divide(x, y):try:result = x / yexcept ZeroDivisionError:logging.error("Attempted to divide by zero")else:logging.info(f"The result of {x}/{y} is {result}")if __name__ == "__main__":# 记录日志logging.debug("Program starts")# 调用函数divide(10, 2)divide(8, 0)# 记录日志logging.debug("Program ends")

在这里插入图片描述

在这个例子中,我们定义了一个divide函数,该函数尝试执行除法运算。如果发生ZeroDivisionError,则记录一个错误日志;否则,记录一个信息日志。通过配置日志,我们可以清晰地看到程序的执行流程,包括开始、结束以及可能发生的异常情况。

二、日志模块的高级特性

2.1 Logger对象

Logger对象是logging模块中用于记录日志的主要接口。我们可以创建自己的Logger对象,也可以使用默认的根Logger对象。Logger对象提供了debug()info()warning()error()critical()等方法来记录不同级别的日志。

2.2 Handler对象

Handler对象用于指定日志的输出目标,如文件、终端、网络等。Handler对象可以添加到Logger对象中,以处理相应级别的日志消息。logging模块提供了多种Handler,如FileHandler(将日志写入文件)、StreamHandler(将日志输出到终端)等。

2.3 Formatter对象

Formatter对象用于指定日志消息的输出格式。通过Formatter,我们可以自定义日志消息的显示方式,包括日期、时间、日志级别、消息内容等。

2.4 示例代码:日志输出到文件

下面是一个将日志输出到文件的示例代码:

import logging# 创建一个Logger对象
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)# 创建一个Formatter对象,指定日志消息的格式
format = '%(asctime)s - %(levelname)s - %(message)s'
formatter = logging.Formatter(format)# 创建一个FileHandler对象,将日志输出到文件
file_handler = logging.FileHandler('output.txt')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)# 将FileHandler对象添加到Logger对象中
logger.addHandler(file_handler)# 创建一个StreamHandler对象,将日志输出到终端
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)# 将StreamHandler对象也添加到Logger对象中
logger.addHandler(console_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")
logger.critical("This is a critical message")# 移除一个Handler(如果需要的话)
# logger.removeHandler(file_handler)# 关闭所有Handlers(通常不需要手动调用,因为Python解释器会在退出时自动处理)
# 但如果程序需要长时间运行,并且希望定期关闭和重新打开日志文件,那么可能需要这样做
# for handler in logger.handlers[:]:
#     handler.close()
#     logger.removeHandler(handler)# 注意:在上面的代码中,我们没有显式地导入sys模块,但如果你打算将日志输出到标准输出(即终端),
# 并且想要使用sys.stdout作为StreamHandler的参数,那么你需要先导入sys模块:
# import sys
# 完整的示例,包括导入sys模块
import logging
import sys# 创建一个Logger对象
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)# 创建一个Formatter对象,指定日志消息的格式
format = '%(asctime)s - %(levelname)s - %(message)s'
formatter = logging.Formatter(format)# 创建一个FileHandler对象,将日志输出到文件
file_handler = logging.FileHandler('output.txt')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)# 创建一个StreamHandler对象,将日志输出到终端
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(formatter)# 将Handlers添加到Logger对象中
logger.addHandler(file_handler)
logger.addHandler(console_handler)# 记录日志
logger.debug("This debug message will appear in the console but not in the file")
logger.info("This info message will appear in both the console and the file")
logger.warning("This is a warning")
logger.error("This is an error")
logger.critical("This is a critical error")

在这里插入图片描述
并且将日志输出到文件
在这里插入图片描述

2.5 日志级别和过滤器

logging模块中,日志级别用于控制日志消息的输出。默认情况下,只有级别大于或等于Logger对象设置的级别的日志消息才会被处理。此外,我们还可以使用过滤器(Filter)来进一步控制哪些日志消息应该被处理。

2.6 日志轮转

对于长时间运行的应用程序,日志文件可能会变得非常大。为了管理这些文件,我们可以使用日志轮转(Log Rotation)功能。然而,logging模块本身并不直接支持日志轮转,但我们可以使用第三方库(如logrotate,在Linux环境下,或者RotatingFileHandler,它是logging.handlers模块的一部分)来实现这一功能。

2.7 日志配置文件

对于复杂的应用程序,直接在代码中配置日志可能会变得繁琐且难以维护。为了解决这个问题,logging模块支持从配置文件中读取日志配置。配置文件可以是Python文件、JSON文件或YAML文件等。使用配置文件可以让我们将日志配置与应用程序代码分离,从而更容易地进行修改和维护。

2.8 示例代码:使用配置文件

下面是一个使用JSON配置文件配置日志的示例。首先,我们创建一个名为logging_config.json的配置文件:

{"version": 1,"disable_existing_loggers": false,"formatters": {"simple": {"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"}},"handlers": {"console": {"class": "logging.StreamHandler","level": "DEBUG","formatter": "simple","stream": "ext://sys.stdout"},"file": {"class": "logging.FileHandler","level": "INFO","formatter": "simple","filename": "app.log"}},"loggers": {"my_app": {"handlers": ["console", "file"],"level": "DEBUG","propagate": false}},
"root": {"handlers": ["console"],"level": "INFO"}
}

然后,在Python代码中,我们可以使用logging.config.dictConfig()函数来加载这个配置文件,并应用配置:


import json
import logging.config# 加载日志配置文件
with open('logging_config.json', 'r') as f:config = json.load(f)
logging.config.dictConfig(config)# 获取配置好的Logger对象
logger = logging.getLogger('my_app')# 记录日志
logger.debug("This debug message will appear in the console and the file")
logger.info("This info message will appear in both the console and the file")
logger.warning("This is a warning")
logger.error("This is an error")
logger.critical("This is a critical error")# 注意:由于我们在配置文件中将'my_app' logger的propagate属性设置为False,
# 设置propagate参数为False,表示不再传递消息到父记录器
# 因此'my_app' logger的日志消息不会传播到root logger。
# 如果我们尝试获取root logger并记录日志,它只会按照root logger的配置(即只输出到控制台)来工作。
root_logger = logging.getLogger()
root_logger.info("This info message from the root logger will only appear in the console")

在这里插入图片描述
看下生成的日志文件
在这里插入图片描述

注意事项

  1. 配置文件中的路径:在配置文件中指定的文件路径(如filename)是相对于当前工作目录的。确保你的应用程序知道在哪里查找这些文件。

  2. 日志级别:每个handler和logger都可以有自己的日志级别。handler的级别决定了哪些级别的日志消息会被该handler处理,而logger的级别决定了哪些级别的日志消息会被发送到该logger的handlers。

  3. 传播(Propagation):默认情况下,如果一个logger没有处理一个日志消息(即它的级别高于logger的级别),那么该消息会被传播到它的父logger。但是,我们可以通过将logger的propagate属性设置为False来阻止这种传播。

  4. 日志配置的性能:在大型应用程序中,日志配置可能会对性能产生影响。确保你仔细规划你的日志策略,以避免不必要的性能开销。

  5. 安全性和隐私:在记录日志时,要特别注意不要记录敏感信息(如密码、个人身份信息等)。始终确保你的日志策略符合你的组织的安全和隐私政策。

  6. 调试和排错:日志是调试和排错的重要工具。确保你的日志策略足够详细,以便在需要时能够提供足够的上下文信息。但是,也要避免记录过多的日志,因为这可能会使问题变得更加难以诊断。

日志的其他一些高级用法

1. 日志上下文(Context)

在复杂的系统中,日志消息可能来自于不同的线程、不同的模块或不同的请求。为了更容易地追踪和关联这些日志消息,我们可以在日志消息中包含上下文信息,如用户ID、请求ID、线程ID等。

虽然Python的logging模块本身不直接支持日志上下文,但我们可以通过几种方式来实现:

  • 使用logging.extra:在记录日志时,可以通过在日志记录方法(如debug(), info(), warning()等)中传递一个extra参数来附加额外的上下文信息。这些信息将作为日志记录的一部分被格式化。

  • 使用上下文管理器:可以编写自定义的上下文管理器,该管理器在进入上下文时设置全局变量或线程局部变量来存储上下文信息,并在退出上下文时清除它们。然后,在日志格式化器中使用这些信息。

  • 使用第三方库:有些第三方库(如structlog)提供了更高级的日志功能,包括自动上下文管理。

2. 异步日志

在异步Python程序中(使用asyncio库),日志记录可能需要特别注意。由于异步代码的执行方式(即事件循环中的协程调度),直接在协程中调用阻塞的日志记录方法(如文件写入)可能会影响程序的性能。

为了解决这个问题,可以使用logging模块的异步支持(如果可用)或编写自定义的异步日志处理器。然而,需要注意的是,Python标准库中的logging模块直到较新的版本才开始提供对异步日志的原生支持。

3. 日志监控和警报

在生产环境中,仅仅记录日志是不够的。我们还需要监控系统中的日志,以便在出现问题时及时得到警报。这通常涉及到日志的集中管理、分析和警报系统。

  • 日志集中管理:可以使用日志聚合工具(如Logstash、Fluentd等)将来自不同源和系统的日志收集到一个中心位置。

  • 日志分析:使用日志分析工具(如Splunk、ELK Stack等)对收集的日志进行搜索、分析和可视化。

  • 警报系统:配置警报规则,以便在检测到特定日志模式(如错误日志、异常日志等)时发送警报(如电子邮件、短信、Slack通知等)。

4. 日志的归档和清理

随着时间的推移,日志文件会积累得越来越多,占用大量的磁盘空间。因此,需要定期归档和清理旧的日志文件。

  • 日志轮转:如前所述,可以使用RotatingFileHandler或第三方工具(如logrotate)来定期轮转日志文件。

  • 归档:将旧的日志文件压缩并存储到归档目录中,以便在需要时检索。

  • 清理:删除过期的日志文件以释放磁盘空间。

5. 安全性考虑

在记录日志时,必须特别注意安全性,以避免敏感信息的泄露。

  • 避免记录敏感信息:确保不要在日志中记录密码、个人身份信息(PII)、密钥等敏感信息。

  • 日志文件的访问控制:确保只有授权用户才能访问日志文件。

  • 加密日志存储:如果日志需要存储在不受信任的位置(如云服务提供商的存储桶),请考虑对日志进行加密。

  • 审计日志:对于需要符合特定法规(如GDPR、HIPAA等)的应用程序,可能需要记录审计日志以证明合规性。

通过以上方法,可以有效地管理和利用Python程序中的日志,从而提高软件的可维护性、可靠性和安全性。

这篇关于【python】Python中的日志模块logging使用技巧与应用实战的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1092310

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4