Python: logging 的巧妙設計

来源:https://www.cnblogs.com/gl1573/archive/2019/01/17/10275699.html
-Advertisement-
Play Games

引言 logging 的基本用法網上很多,這裡就不介紹了。在引入正文之前,先來看一個需求: 假設需要將某功能封裝成類庫供他人使用,如何處理類庫中的日誌? 數年前在一個 C# 開發的項目中,我用了這樣的方法:定義一個 logging 基類,所有需要用到日誌的類都繼承這個基類,這個基類中定義一個 Log ...


引言

logging 的基本用法網上很多,這裡就不介紹了。在引入正文之前,先來看一個需求:

假設需要將某功能封裝成類庫供他人使用,如何處理類庫中的日誌?

數年前在一個 C# 開發的項目中,我用了這樣的方法:定義一個 logging 基類,所有需要用到日誌的類都繼承這個基類,這個基類中定義一個 LogHandler 事件,該事件用於實現具體的記錄日誌動作,同時可以通過將類 A 的 LogHandler 委托掛到類 B 的 LogHandler 上,實現將兩個類的日誌信息添加到一起。

自從看了 python 中 logging 的實現方式,我發現我的做法真是弱爆了。

我在之前的博客 Python:logging.NullHandler 的使用 中介紹了 peewee 框架中的日誌輸出,簡單來說就是 peewee 中定義了一個名為peeweeLogger 並添加了一個 NullHandler,調用者只需要為其添加具體的 Handler 就可以輸出日誌了,非常方便。


假設我們在主程式中也有一個 Logger,調用 peewee 後,我想將兩個日誌輸出到同一個日誌文件中去。顯然將兩個日誌的 FileHandler 指向同一個日誌文件是不可取的,存在併發搶占文件的風險。當然我們也可以將主程式中的 Logger 名字定為 peewee,但這不僅太 low 了,而且如果再調用一個庫,其中也封裝好了一個 Logger,就不好處理了。

樹樁結構的 Logger

Logger 對象被設計為一個樹形結構,它有一個 parent 屬性。logging 中定義了一個名為 rootLogger 作為所有 Logger 的根節點,rootparent 屬性為 Noneroot 是全局的。

當調用

logging.getLogger(name=None)

得到一個 Logger 對象的時候,如果 nameNone,則返回根節點 root。如果 name 中含有 .,比如 name = 'a.b',這時如果已經存在了名為 aLogger,則 a.ba 的子節點,如果不存在名為 aLogger,則 a.broot 的子節點。

child logger 在完成對日誌消息的處理後,預設會將日誌消息傳遞給與它的 parent logger。因此,我們不必為一個應用程式中使用的所有 Logger 定義和配置 handlers,只需要為一個頂層的 Logger 配置 handlers,然後按照需要創建 child loggers 就可足夠了。我們可以通過設置 Loggerpropagate 屬性設置為 False 來關閉這種傳遞機制。

什麼意思呢,我們來看代碼:

import logging

logA = logging.getLogger('a')
logA.setLevel(logging.DEBUG)
logA.addHandler(logging.StreamHandler())

logB = logging.getLogger('a.b')
logB.addHandler(logging.StreamHandler())

輸出結果:

Logger A
Logger B
Logger B

之所以 Logger B 被輸出了 2 次,是因為 logBlogA 的子節點,並且 logB 中也定義了 Handler,所以 logBHandler 輸出了一次,logAHandler 也輸出了一次,就 2 次了。如果想只輸出一次,可以刪掉 logB 中的 Handler。當然,這也是有用處的,尤其是當你手頭沒有日誌管理工具的時候。例如,主程式中需要輸出所有的日誌,以便瞭解程式整體的運行順序,而某模塊的日誌,你想單獨輸出一份,以便清晰瞭解模塊中的報錯或者是執行順序。

之前 peewee 的例子也就很容易解決了,只需要將 peewee 日誌的 parent 屬性設置為主程式的日誌就可以了。

結語

其實這是一個比較容易說明的問題,完全沒必要寫這麼多。我並不想跟大家分享 python 中的 logging 是怎麼用的,而是想和大家分享 logging 如此實現的一種思想,因為我遇到過這個問題,也設計瞭解決方案,然後被完爆了。


 

我的博客即將同步至騰訊雲+社區,邀請大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=1ik0uj4dod1ui


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 經常需要copy一個對象,又怕拷貝有問題,那下麵這段就很方便啦,不用擔心copy只是一個引用了。 / @ values 需要copy的變數 / function deepClone(values) { var copy; if(values == null || typeof values != " ...
  • 實現效果如圖: 功能需求: ①滑鼠進入商品名稱,商品名稱變色,同時對應的物品展示圖片顯示對應的物品,滑鼠移出時候,商品名稱恢複原來的顏色 實現分析: 1.HTML+CSS頁面結構如下: 頁面結構設計中,需要註意的知識點: ①商品li設置邊框時候,只設置下邊框 ②三個列表之間的分割線,使用id為cen ...
  • 一、概念 狀態模式:允許對象在內部狀態改變時改變它的行為,對象看起來好像修改了它的類。這個模式將狀態封裝成為獨立的類,並將動作委托到代表當前狀態的對象,我們知道行為會隨著內部狀態而改變。 一個對象“看起來好像修改了它的類”是什麼意思呢?從客戶的視角來看:如果說你使用的對象能夠完全改變它的行為,那麼你 ...
  • 分散式架構設計:1、橫向分層,將系統在橫向維度上切分成幾個部分,每個部分負責一部分相對比較單一的職責,例如:MVC經典模式。2、縱向分割,將系統功能模塊歸類切分成幾個部分,包裝成高內聚低耦合的模塊單元,不同功能模塊直接通過遠程調用協助工作。3、緩存技術,將是改善系統性能的第一手段,從上到下依次:瀏覽 ...
  • 沒圖,別找了。。。 我在MyEclipse上從SVN中導項目,導下的項目跑不起來,發現tomcat的classes中是空文件夾。 以下是在網上找的其他方法: 1.確保:Project->build automatically 已經被選上。(預設選上) 2.project->clean項目,一般會重新 ...
  • 1. 知乎文章圖片爬取器之二博客背景 昨天寫了知乎文章圖片爬取器的一部分代碼,針對知乎問題的答案json進行了數據抓取,博客中出現了部分寫死的內容,今天把那部分信息調整完畢,並且將圖片下載完善到代碼中去。 首先,需要獲取任意知乎的問題,只需要你輸入問題的ID,就可以獲取相關的頁面信息,比如最重要的合 ...
  • 一、WebSocket與HTTP長輪詢 WebSocket 屬於HTML5 規範的一部分,提供的一種在單個 TCP 連接上進行全雙工通訊的協議。允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,併進行雙向數據傳輸 ...
  • 在前面幾篇討論里我們介紹了在集群環境里的一些編程模式、分散式數據結構及具體實現方式。到目前為止,我們已經實現了把程式任務分配給處於很多伺服器上的actor,能夠最大程度的利用整體系統的硬體資源。這是因為通過akka-cluster能夠把很多伺服器組合成一個虛擬的整體系統,編程人員不需要知道負責運算的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...