日志层次结构及logger.propagate的作用

一、Python logging 模块的层次结构

Python 的 logging 模块提供了一个灵活的日志系统,适用于各种规模的应用程序。其核心设计基于层次化的命名系统,使得日志记录可以按照组织结构进行管理和配置。

1. Logger(日志器)

  • 定义:Logger 是日志记录的核心对象,用于生成日志消息。
  • 命名:每个 Logger 都有一个名称,通常使用点(.)分隔的字符串来表示层次结构,例如 'app''app.module''app.module.submodule'
  • 层次结构:Logger 名称中的点表示层级关系。例如,'app.module''app' 的子 Logger,'app.module.submodule' 又是 'app.module' 的子 Logger。

2. Handler(处理器)

  • 定义:Handler 负责将日志消息发送到特定的目的地,如控制台、文件、网络等。
  • 类型:常用的 Handler 包括 StreamHandler(输出到控制台)、FileHandler(输出到文件)、SMTPHandler(发送邮件)等。
  • 配置:每个 Handler 可以独立配置其日志级别、格式化器等属性。

3. Filter(过滤器)

  • 定义:Filter 提供了更细粒度的控制,用于决定哪些日志消息可以通过特定的 Handler 或 Logger。
  • 用途:可以基于日志属性(如模块名、线程名等)过滤日志消息。

4. Root Logger(根日志器)

  • 定义:Root Logger 是层次结构中的顶级 Logger,其名称为空字符串('')。
  • 作用:所有未显式设置父 Logger 的 Logger 都是根 Logger 的子 Logger。根 Logger 通常配置全局的 Handler 和 Formatter,以确保所有日志消息都有一个默认的处理方式。

5. Logger 的层次关系示意图

根 Logger ('')
├── app
│   ├── app.module
│   │   └── app.module.submodule
│   └── app.other_module
└── another_app└── another_app.module

在上述层次结构中:

  • 'app.module.submodule''app.module' 的子 Logger。
  • 'app.module''app' 的子 Logger。
  • 'app''another_app' 都是根 Logger 的直接子 Logger。

6. 日志消息的传播

当一个 Logger 记录一条日志消息时,消息会首先被当前 Logger 关联的 Handler 处理,然后根据 propagate 属性决定是否将消息传递给父 Logger 进行进一步处理。这种传播机制允许日志消息在层次结构中逐级传递,直到根 Logger。

二、logger.propagate 属性的解释

logger.propagate 是 Python logging 模块中 Logger 对象的一个布尔属性,用于控制日志消息在 Logger 层次结构中的传播行为。理解和合理配置 propagate 对于避免重复日志输出和实现定制化日志处理至关重要。

1. logger.propagate 的基本概念

  • 默认值True
  • 作用
    • propagate=True:日志消息会在当前 Logger 的 Handler 处理完后,继续传递给父 Logger 的 Handler 进行处理。
    • propagate=False:日志消息只由当前 Logger 的 Handler 处理,不会传递给父 Logger。

2. 具体行为示例

假设有以下 Logger 层次结构:

根 Logger ('')
└── app└── app.module

配置

  • 根 Logger 配置了一个 StreamHandler,格式为 ROOT: %(levelname)s: %(message)s
  • app Logger 配置了一个 StreamHandler,格式为 APP: %(levelname)s: %(message)s
  • app.module Logger 配置了一个 StreamHandler,格式为 MODULE: %(levelname)s: %(message)s

示例代码

import logging# 配置根 Logger
root_logger = logging.getLogger()
root_handler = logging.StreamHandler()
root_handler.setFormatter(logging.Formatter('ROOT: %(levelname)s: %(message)s'))
root_logger.addHandler(root_handler)
root_logger.setLevel(logging.DEBUG)# 配置 'app' Logger
app_logger = logging.getLogger('app')
app_handler = logging.StreamHandler()
app_handler.setFormatter(logging.Formatter('APP: %(levelname)s: %(message)s'))
app_logger.addHandler(app_handler)
app_logger.setLevel(logging.DEBUG)# 配置 'app.module' Logger
module_logger = logging.getLogger('app.module')
module_handler = logging.StreamHandler()
module_handler.setFormatter(logging.Formatter('MODULE: %(levelname)s: %(message)s'))
module_logger.addHandler(module_handler)
module_logger.setLevel(logging.DEBUG)print("=== propagate=True ===")
module_logger.propagate = True
module_logger.debug('This is a debug message with propagate=True.')print("\n=== propagate=False ===")
module_logger.propagate = False
module_logger.debug('This is a debug message with propagate=False.')

预期输出

=== propagate=True ===
MODULE: DEBUG: This is a debug message with propagate=True.
APP: DEBUG: This is a debug message with propagate=True.
ROOT: DEBUG: This is a debug message with propagate=True.=== propagate=False ===
MODULE: DEBUG: This is a debug message with propagate=False.

解释

  1. propagate=True(默认)

    • 日志消息首先由 app.module Logger 关联的 module_handler 处理,输出 "MODULE: DEBUG: This is a debug message with propagate=True."
    • 然后,消息传递给父 Logger app,由 app_handler 处理,输出 "APP: DEBUG: This is a debug message with propagate=True."
    • 最后,消息继续传递给根 Logger,由 root_handler 处理,输出 "ROOT: DEBUG: This is a debug message with propagate=True."
  2. propagate=False

    • 日志消息仅由 app.module Logger 关联的 module_handler 处理,输出 "MODULE: DEBUG: This is a debug message with propagate=False."
    • 消息不会传递给父 Logger app 或根 Logger。

3. 使用场景

  • 避免重复日志输出
    在多层次 Logger 配置中,如果不适当设置 propagate,可能导致同一条日志消息被多个 Handler 重复处理。例如,日志同时被子 Logger 和父 Logger 的 Handler 输出。通过将子 Logger 的 propagate 设置为 False,可以避免这种情况。

  • 定制化日志处理
    有时希望特定 Logger 的日志消息只由其自身的 Handler 处理,而不受父 Logger 的影响。此时,可以将该 Logger 的 propagate 设置为 False,实现独立的日志处理逻辑。

4. 综合示例:结合层次结构和 logger.propagate

假设有以下应用场景:

  • 根 Logger:记录所有 WARNING 及以上级别的日志到文件 app.log
  • app.module Logger:记录所有 DEBUG 及以上级别的日志到控制台,并且不希望这些日志再传递给根 Logger

配置代码

import logging# 定义日志器
root_logger = logging.getLogger()
root_logger.setLevel(logging.WARNING)
file_handler = logging.FileHandler('app.log')
file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(file_formatter)
root_logger.addHandler(file_handler)app_module_logger = logging.getLogger('app.module')
app_module_logger.setLevel(logging.DEBUG)
console_handler = logging.StreamHandler()
console_formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(console_formatter)
app_module_logger.addHandler(console_handler)
app_module_logger.propagate = False  # 禁止传播到根 Logger# 日志记录
app_module_logger.debug('Debug message from app.module.')  # 仅输出到控制台
app_module_logger.warning('Warning message from app.module.')  # 输出到控制台和文件(由于 propagate=False,不会输出到文件)root_logger.warning('Warning message from root logger.')  # 仅输出到文件

预期行为

  • "Debug message from app.module." 仅显示在控制台,因为它的级别是 DEBUG,且 propagate=False,不会传递到根 Logger。
  • "Warning message from app.module." 显示在控制台,并记录到 app.log 文件中,因为它的级别是 WARNINGapp_module_logger 有独立的 Handler,并且 propagate=False 允许它独立记录。
  • "Warning message from root logger." 仅记录到 app.log 文件中,由根 Logger 处理。

文件 app.log 内容(示例):

2024-04-27 12:34:56,789 - root - WARNING - Warning message from root logger.

控制台输出

app.module - DEBUG - Debug message from app.module.
app.module - WARNING - Warning message from app.module.

5. 注意事项

  • 配置顺序:确保在配置 Logger、Handler 和 Formatter 时,按照正确的顺序进行,以避免配置错误或遗漏。
  • 避免 Handler 重复:如果 Logger 的 propagateTrue,并且父 Logger 也有相同的 Handler,可能导致日志消息被重复处理。使用 propagate=False 可有效避免此类问题。
  • 性能考虑:虽然 propagate 对性能的影响较小,但在高频率的日志记录场景中,过多的传播可能会带来一定的开销。合理配置 propagate 有助于优化日志系统的性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/64044.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何配置OSB连接数据连接/读取超时

1.Oracle DB OSB中的DBAdapter的查询超时参数配置没用,要解决接口超时问题,需要在console中的数据源配置超时参数: oracle.net.CONNECT_TIMEOUT30000 oracle.net.READ_TIMEOUT30000 添加图片注释,不超过 140 字(可选…

一起学Git【第六节:查看版本差异】

git diff是 Git 版本控制系统中用于展示差异的强大工具。他可以用于查看文件在工作区、暂存区和版本库之间的差异、任意两个指定版本之间的差异和两个分支之间的差异等,接下来进行详细的介绍。 1.显示工作区与暂存区之间的差异 # 显示工作区和暂存区之间的差异,后面不加参数…

Python数据处理——re库与pydantic的使用总结与实战,处理采集到的思科ASA防火墙设备信息

目录 Python正则表达式re库的基本用法 引入re库 各函数功能 总结 使用方法举例 正则表达式语法与书写方式 正则表达式的常用操作符 思科ASA防火墙数据 数据1 数据2 书写正则表达式 Python中pydantic的使用 导入基础数据模板 根据数据采集目标定义Pydantic数据类型…

`we_chat_union_id IS NOT NULL` 和 `we_chat_union_id != ‘‘` 这两个条件之间的区别

文章目录 1、什么是空字符串?2、两个引号之间加上空格 好的,我们来详细解释一下 we_chat_union_id IS NOT NULL 和 we_chat_union_id ! 这两个条件之间的区别,以及它们在 SQL 查询中的作用: 1. we_chat_union_id IS NOT NULL 含…

如何利用AWS监听存储桶并上传到tg bot

业务描述: 需要监听aws的存储中的最新消息,发送新的消息推送到指定tg的频道。 主要流程: 1.上传消息到s3存储桶(不做具体描述) 2.通过aws的lambda监听s3存储桶的最新消息(txt文件) 3.将txt文件…

HarmonyOS NEXT 实战之元服务:静态案例效果---查看国内航班服务

背景: 前几篇学习了元服务,后面几期就让我们开发简单的元服务吧,里面丰富的内容大家自己加,本期案例 仅供参考 先上本期效果图 ,里面图片自行替换 效果图1完整代码案例如下: Index代码 import { authen…

Windows11家庭版启动Hyper-V

Hyper-V 是微软的硬件虚拟化产品,允许在 Windows 上以虚拟机形式运行多个操作系统。每个虚拟机都在虚拟硬件上运行,可以创建虚拟硬盘驱动器、虚拟交换机等虚拟设备。使用虚拟化可以运行需要较旧版本的 Windows 或非 Windows 操作系统的软件,以…

为什么深度学习和神经网络要使用 GPU?

为什么深度学习和神经网络要使用 GPU? 本篇文章的目标是帮助初学者了解 CUDA 是什么,以及它如何与 PyTorch 配合使用,更重要的是,我们为何在神经网络编程中使用 GPU。 图形处理单元 (GPU) 要了解 CUDA,我们需要对图…

图像处理-Ch7-快速小波变换和小波包

个人博客!无广告观看,因为这节内容太多了,有点放不下,分了三节 文章目录 快速小波变换(The Fast Wavelet Transform)与两频段子带编译码系统的关系例:计算一维小波变换 一维快速小波反变换例:计算一维小波…

[项目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 测试及总结

目录 编写http_server模块 1. 引入cpp-httplib到项目中 2. cpp-httplib的使用介绍 3. 正式编写http_server 九、添加日志到项目中 十、编写前端模块 十一. 详解传 gitee 十二、项目总结 项目的扩展 写在前面 [项目详解][boost搜索引擎#1] 概述 | 去标签 | 数据清洗 |…

xxl-job 简单的入门到实战

本文是参考官方文档自己实践一次,纯享版,大致也是作者边写博客边去跟着官方文档实现 一、前期准备 1、官网地址 GitHub地址: GitHub - xuxueli/xxl-job: A distributed task scheduling framework.(分布式任务调度平台XXL-JOB&…

【教程】通过Docker运行AnythingLLM

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 官方教程:Local Docker Installation ~ AnythingLLM 1、先创建一个目录用于保存anythingllm的持久化文件: sudo mkdir /app su…

若依(RuoYi-Vue)+Flowable工作流前后端整合教程

此教程适合若依前后端分离项目,其他项目可以在扩展列表中进行查找。 近期公司里需要对很久以前的RuoYi-Vue前后端分离项目扩展出flowable的功能,当然这个重任也是落在了我的身上(不然也不会有这篇文章),然后我在官网看…

ubuntu 网络管理--NetworkManager

ubuntu 网络管理--NetworkManager 1 介绍2 NetworkManager 命令2 nmcli 命令显示可用的wifi AP连接wifi检查网络连接 ?? 如何删除删除网络连接查看设备状态添加一个新的以太网连接设置静态 IP 地址启用并测试连接添加新的wifi连接 3 其他命令参考 1 介绍 NetworkManager 是标…

水库大坝三维模型的开发和使用3Dmax篇

成果图 开发过程 工具插件three.js先加载模型做水体衔接水位测量标尺水位标记断面标记大坝监测点打点 上代码&#xff0c;技术交流V: bloxed <template><div class"box w100 h100"><el-row :gutter"20" v-loading"loading"e…

计算机毕设-基于springboot的校园招聘网站的设计与实现(附源码+lw+ppt+开题报告)

博主介绍&#xff1a;✌多个项目实战经验、多个大型网购商城开发经验、在某机构指导学员上千名、专注于本行业领域✌ 技术范围&#xff1a;Java实战项目、Python实战项目、微信小程序/安卓实战项目、爬虫大数据实战项目、Nodejs实战项目、PHP实战项目、.NET实战项目、Golang实战…

重生之我在异世界学编程之C语言:深入动态内存管理收尾 + 柔性数组篇

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文常见的动态内存管理错误&#xf…

无人直播源码

DY无人直播系统架构设计介绍 在DY等短视频平台的直播中&#xff0c;无人直播系统能够提供自动化、智能化的互动体验&#xff0c;既减轻了主播的工作量&#xff0c;又提升了观众的参与感。以下是一个典型的无人直播系统架构设计&#xff0c;包含全局配置、点对点互动、产品话术、…

被裁20240927 --- 嵌入式硬件开发 前篇

前篇主要介绍一些相关的概念&#xff0c;用于常识扫盲&#xff0c;后篇开始上干货&#xff01; 他捧着一只碗吃过百家的饭 1. 处理器芯片1.1 处理器芯片制造商一、 英特尔&#xff08;Intel&#xff09;二、 三星&#xff08;SAMSUNG&#xff09;三、 高通&#xff08;Qualcomm…

【Linux】进程间通信 -> 匿名管道命名管道

进程间通信的目的 数据传输&#xff1a;一个进程许需要将它的数据发送给另外一个进程。资源共享&#xff1a;多个进程之间共享同样的资源。通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它们发生了某种事件&#xff08;如进程终止时要通知父进程…