日志層次結構及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.pswp.cn/web/64044.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64044.shtml
英文地址,請注明出處:http://en.pswp.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數據類型…

Yolo11改進策略:Head改進|DynamicHead,利用注意力機制統一目標檢測頭部|即插即用

摘要 論文介紹 本文介紹了一種名為DynamicHead的模塊,該模塊旨在通過注意力機制統一目標檢測頭部,以提升目標檢測的性能。論文詳細闡述了DynamicHead的工作原理,并通過實驗證明了其在COCO基準測試上的有效性和效率。 創新點 DynamicHead模塊的創新之處在于它首次嘗試在一…

`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,我們需要對圖…

每天五分鐘機器學習:核函數

本文重點 在學習支持向量機算法之前,我們要繼續學習一些數學基礎,本文我們將學習核函數的概念。當數據線性不可分的時候,此時就需要核函數出場了,它可以將低維不可分的數據映射到高維可分數據,此時就可以完成數據分類了。 核函數的定義 核函數K(x, y)定義為兩個數據點x…

MaaS(Model as a Service)

1.MasS是什么? Model as a Service(MaaS)是一種云計算服務模式,它允許用戶通過互聯網訪問和使用機器學習模型,而不需要自行構建和維護這些模型。MaaS提供了模型的托管、管理和監控,使用戶能夠專注于應用程…

圖像處理-Ch7-快速小波變換和小波包

個人博客!無廣告觀看,因為這節內容太多了,有點放不下,分了三節 文章目錄 快速小波變換(The Fast Wavelet Transform)與兩頻段子帶編譯碼系統的關系例:計算一維小波變換 一維快速小波反變換例:計算一維小波…

KAFKA 權威指南筆記(一)究竟應該配置多少個BROKER?

一個KAFKA集群需要多少個BROKER? 一個單獨的Kafka服務器被叫做BROKER,BROKER可以處理數千個分區以及每秒百萬級別的消息量。由BROKER組成了“集群”(其中由集群控制器角色的BROKER是從成員中選舉出來的,負責控制管理工作&#xf…

【ES6復習筆記】函數參數的默認值(6)

在ES6中,函數參數默認值是一個非常有用的特性,它允許你在定義函數時為參數指定一個默認值。如果在調用函數時沒有提供相應的參數值,那么函數將使用默認值。 1. 形參初始值 具有默認值的參數,一般位置要靠后。這是一個潛規則&…

WebRtc webrtc-streamer部署

文章目錄 本文檔只是為了留檔方便以后工作運維,或者給同事分享文檔內容比較簡陋命令也不是特別全,不適合小白觀看,如有不懂可以私信,上班期間都是在得 WebRtc webrtc-streamer 部署 docker run -p 8000:8000 -it mpromonet/webrt…

Spring Boot中冪等性的應用

在 Spring Boot 中,冪等性是實現分布式系統設計和接口調用的一個重要概念,尤其在高并發、分布式環境下,確保接口重復調用不會引發系統數據異常至關重要。 冪等性概念 冪等性(Idempotence)是指一次請求和重復多次請求…

leetcode 7. 整數反轉

class Solution { public: int reverse(int x) { long long n0; if(x0) return 0; while(x%100) { xx/10; } while(x!0) { nn*10x%10; xx/10; } if(n<-2147483648||n>2147483647) return 0; return n; } };

[項目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 測試及總結

目錄 編寫http_server模塊 1. 引入cpp-httplib到項目中 2. cpp-httplib的使用介紹 3. 正式編寫http_server 九、添加日志到項目中 十、編寫前端模塊 十一. 詳解傳 gitee 十二、項目總結 項目的擴展 寫在前面 [項目詳解][boost搜索引擎#1] 概述 | 去標簽 | 數據清洗 |…

xxl-job 簡單的入門到實戰

本文是參考官方文檔自己實踐一次&#xff0c;純享版&#xff0c;大致也是作者邊寫博客邊去跟著官方文檔實現 一、前期準備 1、官網地址 GitHub地址&#xff1a; GitHub - xuxueli/xxl-job: A distributed task scheduling framework.&#xff08;分布式任務調度平臺XXL-JOB&…

Centos7, 使用yum工具,出現 Could not resolve host: mirrorlist.centos.org

在 CentOS 7 中使用 yum 工具時&#xff0c;如果出現 "Could not resolve host: mirrorlist.centos.org" 的錯誤&#xff0c;通常是因為默認的鏡像源無法訪問。以下是一些常用的解決方法&#xff1a; 檢查網絡連接&#xff1a;首先使用 ping 命令測試網絡連接是否正常…