[Python]使用logging創造改良版日誌紀錄器,不重複紀錄

閱讀時間約 11 分鐘

呈上篇,若是在大型系統中使用,重複被調用時,在每次紀錄時都會創建一個新的 FileHandler,這會導致日誌處理器不斷累積,從而使日誌重複記錄。

[Python]使用logging創建兩個以上的日誌紀錄

使用__new__的方法來避免重複調用

改良後

setup_logger 方法中創建一次 FileHandler,並確保不重複創建它。可以在類別中新增一個來initialized確保 FileHandler 只被創建一次。

import os
import logging
import inspect
from datetime import datetime
from threading import Lock

class WriteLogTxt:
_instances = {}
_lock = Lock()

def __new__(cls, file_path, file_name):
with cls._lock:
key = (file_path, file_name)
if key not in cls._instances:
instance = super(WriteLogTxt, cls).__new__(cls)
cls._instances[key] = instance
instance.__initialized = False
return cls._instances[key]

def __init__(self, file_path, file_name):
if self.__initialized:
return
self.file_path = file_path
self.file_name = file_name
self.logger = None
self.logger_initialized = False
self.__initialized = True

def setup_logger(self):
if not self.logger_initialized:
now = datetime.now()
year_month = now.strftime("%Y/%m")
log_folder = os.path.join(self.file_path, year_month)
if not os.path.exists(log_folder):
os.makedirs(log_folder)
log_format = '%(asctime)s [%(levelname)s] %(msg)s'
file_handler = logging.FileHandler(os.path.join(log_folder, f"{self.file_name}_{now.date()}.log"))
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(logging.Formatter(log_format, datefmt='%Y/%m/%d %H:%M:%S'))

self.logger = logging.getLogger(f"{self.file_path}/{self.file_name}")
self.logger.setLevel(logging.INFO)
self.logger.addHandler(file_handler)
self.logger_initialized = True

def write_log_info(self, log_content):
self.setup_logger()
caller_frame = inspect.stack()[1]
caller_filename = caller_frame.filename
caller_lineno = caller_frame.lineno
match = os.path.basename(caller_filename)
self.logger.info(f"[File name :{match}][Line :{caller_lineno}]{log_content}")

def write_log_warning(self, log_content):
self.setup_logger()
caller_frame = inspect.stack()[1]
caller_filename = caller_frame.filename
caller_lineno = caller_frame.lineno
match = os.path.basename(caller_filename)
self.logger.warning(f"[File name :{match}][Line :{caller_lineno}]{log_content}")


# 創建並設置日誌記錄器
for i in range(10):
    log_obj1 = WriteLogTxt('D:/crab/crab/log', 'Log')
    log_obj1.setup_logger()
    log_obj1.write_log_info("This is a log message")

即使不斷重複被調用類別,也只會被創建一次,不會在有重複紀錄的bug

raw-image

針對__new__ 方法與__init__ 方法 更詳細的說明

在 Python 中,__new__ 方法負責創建一個新的實例。這個方法在 __init__ 方法之前被調用,它允許我們控制對象的創建過程。

這段程式碼使用 __new__ 方法來實現單例模式,以確保每個 file_pathfile_name 組合只會創建一個實例。

詳細說明如下:

__new__ 方法

def __new__(cls, file_path, file_name):
with cls._lock:
key = (file_path, file_name)
if key not in cls._instances:
instance = super(WriteLogTxt, cls).__new__(cls)
cls._instances[key] = instance
instance.__initialized = False
return cls._instances[key]
  • cls: 代表這個類本身,它在類方法中被用作第一個參數。
  • file_pathfile_name: 用於唯一標識每個日誌實例的路徑和文件名。

步驟解析

  1. 加鎖with cls._lock: 使用 Lock 來確保此方法在多線程環境下是線程安全的。
  2. 生成唯一鍵key = (file_path, file_name),通過組合 file_pathfile_name 來生成一個唯一鍵。
  3. 檢查實例存在if key not in cls._instances:,如果這個唯一鍵不在 _instances 字典中,則創建一個新的實例。
  4. 創建實例instance = super(WriteLogTxt, cls).__new__(cls) 使用 super() 調用基類(即 object)的 __new__ 方法來創建實例。
  5. 存儲實例cls._instances[key] = instance 將新創建的實例存儲在 _instances 字典中。
  6. 設置初始化標記instance.__initialized = False,設置 __initialized 標記為 False,表示實例尚未被初始化。
  7. 返回實例return cls._instances[key] 返回對應鍵的實例,保證每個鍵只有一個實例。


__init__ 方法

__init__ 方法負責初始化新創建的實例。

當一個實例被創建後(即調用了 __new__ 方法後),__init__ 方法被調用來初始化該實例。詳細說明如下:

def __init__(self, file_path, file_name):
if self.__initialized:
return
self.file_path = file_path
self.file_name = file_name
self.logger = None
self.logger_initialized = False
self.__initialized = True

步驟解析

  1. 檢查是否已初始化if self.__initialized: 如果 __initialized 標記為 True,表示這個實例已經被初始化過了,直接返回,不做重複初始化。
  2. 設置屬性
    • self.file_path = file_path:設置實例的文件路徑屬性。
    • self.file_name = file_name:設置實例的文件名屬性。
    • self.logger = None:初始化 logger 屬性為 None。
    • self.logger_initialized = False:初始化 logger_initialized 標記為 False,表示日誌記錄器尚未初始化。
  3. 設置初始化標記self.__initialized = True,設置 __initialized 標記為 True,表示實例已經被初始化。



119會員
201內容數
本業是影像辨識軟體開發,閒暇時間進修AI相關內容,將學習到的內容寫成文章分享。
留言0
查看全部
發表第一個留言支持創作者!
螃蟹_crab的沙龍 的其他內容
在處理數據時,最可能會遇到數據中含有None的時候,若沒有處理就進行運算就會造成程式崩潰或者報錯 數據中含有None input_list = [(42, 292), (28, 296), (999, 92), (993, 46), (219, 4), (279, 2), (None, None
在檢查列表中含有tuple的座標點時,若要給其他演算法做運算時若有其中有tuple有空值時,就會報錯。 本文主要介紹兩種方法可以檢查是否有空值 程式範例1 positon_list =[(42,123),(None,None),(22,11)] for cord in positon_lis
對於程式卡頓的問題,如何分析程式碼占用多少記憶體,如何釋放或改寫,可以先用python內建的tracemalloc模組來追蹤 Python 分配的記憶體區塊。 本文將介紹最簡單的用法,來分析一段程式碼占用了多少記憶體。 結果呈現 印出當前使用的記憶體,與峰值記憶體使用量。 程式範例 i
在離線環境需要安裝Python套件時就相當的麻煩,需要先下載好套件包,在打指令安裝,若套件數量一多時就會相當麻煩。 本文將介紹如何利用兩行指令快速的安裝整個資料夾的套件。
在讀取檔案時,最怕路徑的問題,常常會有路徑錯誤造成的異常報錯。 為了避免諸如此類的問題發生,明白程式的當前目錄與檔案的路徑是很重要的。 可以利用os 模組是 Python 中的一個標準庫,提供了許多與操作系統的功能。 以下是一些常用的 os 模組基本操作及其範例: 1. os.getcwd
解讀JSON 字串 首先,你需要使用 Python 的 json 模組來解讀JSON 字串。 JSON的基本結構: 由花括號 {} 包圍,內部是鍵值對的集合,每個鍵值對之間用逗號分隔。 鍵是字串類型,值可以是任何JSON支持的資料類型(字串、數字、布林值、陣列、物件或 null)。 {
在處理數據時,最可能會遇到數據中含有None的時候,若沒有處理就進行運算就會造成程式崩潰或者報錯 數據中含有None input_list = [(42, 292), (28, 296), (999, 92), (993, 46), (219, 4), (279, 2), (None, None
在檢查列表中含有tuple的座標點時,若要給其他演算法做運算時若有其中有tuple有空值時,就會報錯。 本文主要介紹兩種方法可以檢查是否有空值 程式範例1 positon_list =[(42,123),(None,None),(22,11)] for cord in positon_lis
對於程式卡頓的問題,如何分析程式碼占用多少記憶體,如何釋放或改寫,可以先用python內建的tracemalloc模組來追蹤 Python 分配的記憶體區塊。 本文將介紹最簡單的用法,來分析一段程式碼占用了多少記憶體。 結果呈現 印出當前使用的記憶體,與峰值記憶體使用量。 程式範例 i
在離線環境需要安裝Python套件時就相當的麻煩,需要先下載好套件包,在打指令安裝,若套件數量一多時就會相當麻煩。 本文將介紹如何利用兩行指令快速的安裝整個資料夾的套件。
在讀取檔案時,最怕路徑的問題,常常會有路徑錯誤造成的異常報錯。 為了避免諸如此類的問題發生,明白程式的當前目錄與檔案的路徑是很重要的。 可以利用os 模組是 Python 中的一個標準庫,提供了許多與操作系統的功能。 以下是一些常用的 os 模組基本操作及其範例: 1. os.getcwd
解讀JSON 字串 首先,你需要使用 Python 的 json 模組來解讀JSON 字串。 JSON的基本結構: 由花括號 {} 包圍,內部是鍵值對的集合,每個鍵值對之間用逗號分隔。 鍵是字串類型,值可以是任何JSON支持的資料類型(字串、數字、布林值、陣列、物件或 null)。 {
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
20240802   這裡在挑戰寫365篇咚咚,會記錄我的日常,可能是生活、是閱讀、是回憶、是思考,都小小的,歡迎你來,也歡迎你看,也歡迎跟我說說話。 如果你願意陪著我一起挑戰,我會非常非常高興並且感謝。
Thumbnail
透過每日紀錄寫下工作與生活的點滴,反思自我的管理與處理狀況以及工作效率與成就感等部分。計畫進行屋內裝潢也是從生活紀錄開始的新計劃。同時也透過視頻學習職場處事的思考脈絡,以提升自己的工作方式。這篇日記著重於工作與生活間的反思和成長。
  筆記軟體裡累積了不少構思文章留下的廢案。沒寫的原因多半是因為覺得有資料要查,當下沒什麼時間,所以想說之後有空再弄。但我們都知道所謂「有空再弄」往往會走向怎樣的結果:它會一直放著、然後越積越多。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
瞭解如何在Xcode15及以上使用Logger進行更好的程式debug。Logger可以更好的組織Log,但也有一些缺點需要注意。本文將介紹Logger的基本使用方式,以及一些注意事項。
Thumbnail
在數位筆記管理中,標籤混亂是一個常見問題,尤其是當出現許多重複標籤時。例如,“#人力資源”和“#人力資源管理”,“#旅行”和“#旅遊”,“#啟發”和“#啟示”這些類似的標籤會導致分類繁複而臃腫,長期下來不僅無益反而有害。
Thumbnail
工具功能 (1) 彈性任意查詢檔案,如對來源目錄設定,檔案修改日期 設定,檔名特定字串或副檔名設定後,自動查出明細,並可展開至各階子目錄處理     (2) 依查詢後結果,可產出 LIST ,提供查詢結果之確認,再依此對檔案作複 (3) 可對檔案作移動,複製至別處,刪除處理,使電腦可騰出硬碟空間
Thumbnail
大數據時代下,Log的多元應用至關重要。Log生成龐大,格式各異,特別金融業需合規。探討Log廣泛應用、資訊安全、IT管理和商業決策。建立Log管理系統核心深入法規,強化IT治理、權限控管。一站式Log管理平台,確保資訊安全合規。
Thumbnail
關於多執行緒/多行程的使用方式 在Python 3.2版本之後加入了「concurrent.futures」啟動平行任務, 它可以更好的讓我們管理多執行緒/多行程的應用場景,讓我們在面對這種併發問題時可以不必害怕, 用一個非常簡單的方式就能夠處裡, 底下我們將為您展示一段程式碼: imp
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
Thumbnail
Faker昨天真的太扯了,中國主播王多多點評的話更是精妙,分享給各位 王多多的點評 「Faker是我們的處境,他是LPL永遠繞不開的一個人和話題,所以我們特別渴望在決賽跟他相遇,去直面我們的處境。 我們曾經稱他為最高的山,最長的河,以為山海就是盡頭,可是Faker用他28歲的年齡...
Thumbnail
20240802   這裡在挑戰寫365篇咚咚,會記錄我的日常,可能是生活、是閱讀、是回憶、是思考,都小小的,歡迎你來,也歡迎你看,也歡迎跟我說說話。 如果你願意陪著我一起挑戰,我會非常非常高興並且感謝。
Thumbnail
透過每日紀錄寫下工作與生活的點滴,反思自我的管理與處理狀況以及工作效率與成就感等部分。計畫進行屋內裝潢也是從生活紀錄開始的新計劃。同時也透過視頻學習職場處事的思考脈絡,以提升自己的工作方式。這篇日記著重於工作與生活間的反思和成長。
  筆記軟體裡累積了不少構思文章留下的廢案。沒寫的原因多半是因為覺得有資料要查,當下沒什麼時間,所以想說之後有空再弄。但我們都知道所謂「有空再弄」往往會走向怎樣的結果:它會一直放著、然後越積越多。
Thumbnail
在網路速度有限的情況下,依序記錄不斷產生的資訊,能統計使用者在頁面上操作了哪些功能。
Thumbnail
瞭解如何在Xcode15及以上使用Logger進行更好的程式debug。Logger可以更好的組織Log,但也有一些缺點需要注意。本文將介紹Logger的基本使用方式,以及一些注意事項。
Thumbnail
在數位筆記管理中,標籤混亂是一個常見問題,尤其是當出現許多重複標籤時。例如,“#人力資源”和“#人力資源管理”,“#旅行”和“#旅遊”,“#啟發”和“#啟示”這些類似的標籤會導致分類繁複而臃腫,長期下來不僅無益反而有害。
Thumbnail
工具功能 (1) 彈性任意查詢檔案,如對來源目錄設定,檔案修改日期 設定,檔名特定字串或副檔名設定後,自動查出明細,並可展開至各階子目錄處理     (2) 依查詢後結果,可產出 LIST ,提供查詢結果之確認,再依此對檔案作複 (3) 可對檔案作移動,複製至別處,刪除處理,使電腦可騰出硬碟空間
Thumbnail
大數據時代下,Log的多元應用至關重要。Log生成龐大,格式各異,特別金融業需合規。探討Log廣泛應用、資訊安全、IT管理和商業決策。建立Log管理系統核心深入法規,強化IT治理、權限控管。一站式Log管理平台,確保資訊安全合規。
Thumbnail
關於多執行緒/多行程的使用方式 在Python 3.2版本之後加入了「concurrent.futures」啟動平行任務, 它可以更好的讓我們管理多執行緒/多行程的應用場景,讓我們在面對這種併發問題時可以不必害怕, 用一個非常簡單的方式就能夠處裡, 底下我們將為您展示一段程式碼: imp