[Python]使用多個logging如何追蹤呼叫它的函式及行數

閱讀時間約 9 分鐘

呈上次使用logging來撰寫日誌,利用類別包裝的方式,可實現多個日誌紀錄器,但發現這樣就失去它原先,可以回傳是誰呼叫他並記錄行數的功能。

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

若開啟函式名稱、行數及訊息的功能,就會像這樣,幾乎都是記錄到,我定義中類別的函式,兩個檔案都是寫一樣的內容,就達不到,我們想要的結果。

raw-image

那要怎麼解呢?


若不是要實現多個logging紀錄器,加上以下程式碼,不要用類別包裝,直接用logging這樣就可以很方便地去使用logging的套件就好。

# 設定日誌格式,包含日期時間、日誌等級、函式名稱、行數及訊息
log_format = "%(asctime)s - %(levelname)s - %(funcName)s - %(lineno)d - %(message)s"

在 Python 中,可以使用 inspect 模組來取得目前被呼叫的函式名稱和行數。

我們利用inspect 模組來實現追蹤呼叫logging的檔案名稱及行數。

完整程式範例

import os
import re
import logging
import inspect
from datetime import datetime

class WriteLogTxt:
'''
setup_logger 設置logging格式及創立文件夾
write_log_info 指定檔案名稱及log內容輸入
write_log_warning
'''
def __init__(self,file_path,file_name):
self.file_path = file_path
self.file_name = file_name

def setup_logger(self):
'''
設置logging格式及創立文件夾
'''
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 - %(message)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))

# 設置logger
self.logger = logging.getLogger(self.file_name)
self.logger.setLevel(logging.INFO)
self.logger.addHandler(file_handler)

# 指定檔案名稱及log內容輸入
def write_log_info(self,log_content):
'''
log_content : Log
'''
# 寫入log
# 獲取呼叫者的資訊
caller_frame = inspect.currentframe().f_back
frame_info = inspect.getframeinfo(caller_frame)
file_path = frame_info.filename
line_number = frame_info.lineno
pattern = r'[^\\]+$'
file_name = re.search(pattern, file_path).group(0)
self.logger.info(f"file_name: [{file_name}],line_number: [{line_number}] {log_content}")

額外開啟兩個py,來呼叫WriteLogTxt撰寫日誌紀錄

取名為module_1.py與module_2.py

from test import WriteLogTxt

#調用第一個log_obj寫入log
log_obj = WriteLogTxt('D:/CRABpy/write/log','sample_1')
log_obj.setup_logger()
log_obj.write_log_info('test_1')
from test import WriteLogTxt

#調用第二個log_obj寫入log
log_obj_2 = WriteLogTxt('D:/CRABpy/write/log','sample_2')
log_obj_2.setup_logger()
log_obj_2.write_log_info('test_2')
raw-image

成功實現了,追蹤呼叫logging的檔案名稱及行數。

主要是新增了以下程式碼

# 獲取呼叫者的資訊
caller_frame = inspect.currentframe().f_back
frame_info = inspect.getframeinfo(caller_frame)
file_path = frame_info.filename
line_number = frame_info.lineno
pattern = r'[^\\]+$'
file_name = re.search(pattern, file_path).group(0)

詳細說明

  • 獲取當前框架:
    caller_frame = inspect.currentframe().f_back
    inspect.currentframe() 函式返回當前的堆疊框架物件。f_back 屬性指向上一個堆疊框架,這裡的 caller_frame 即為呼叫當前函式的框架。
  • 獲取框架資訊:
    frame_info = inspect.getframeinfo(caller_frame)
    inspect.getframeinfo(frame) 函式接收一個框架物件並返回一個包含檔案名稱、行數、函式名稱等資訊的物件。這裡的 frame_info 包含呼叫函式所在的檔案名稱和行數。
  • 提取檔案路徑:
    python複製程式碼file_path = frame_info.filename
    frame_info.filename 返回呼叫函式的檔案路徑。
  • 提取行數:
    line_number = frame_info.lineno
    frame_info.lineno 返回呼叫函式所在的行數。
  • 定義正規表達式模式:
    pattern = r'[^\\]+$'
    這個正規表達式模式 [^\\]+$ 匹配最後一個反斜杠(\)之後的所有字符,直到字符串的結尾。具體來說:
    • [^\\] 匹配任何不是反斜杠的字符。
    • + 匹配前一個字符集合的一次或多次出現。
    • $ 匹配字符串的結尾。
  • 應用正規表達式提取檔案名稱:
    file_name = re.search(pattern, file_path).group(0)
    re.search(pattern, file_path) 尋找符合模式的第一個匹配,返回一個 Match 物件。group(0) 返回整個匹配的字符串,即檔案名稱。

這段程式碼的目的是從呼叫函式的框架中提取檔案名稱和行數,並使用正規表達式從完整檔案路徑中擷取出檔案名稱。例如,給定完整路徑 'f:\\python\\opencv\\pathinputdata\\module_1.py',它會提取出 module_1.py


52會員
112內容數
Python程式設計師,不是在學習就是在學習的路上
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
[Python] 使用 PyInstaller 將程式碼轉換成執行檔PyInstaller 是一個強大的工具,可以將 Python 程式碼打包成獨立的可執行檔案,讓你的程式可以在沒有 Python 解釋器的情況下運行。這對於分享和分發你的 Python 應用程式非常有用。以下是使用 PyInstaller 的基本步驟:
Thumbnail
avatar
Pochi
2023-08-15
大幅提升執行效率:解析Python多執行緒和多進程的效能差異與使用情境最近在調整跟優化效能時,又來複習了 Multi-threading 和 Multiprocessing 的概念,在面對大數據時,能夠有效利用多核心處理器的能力,對於提升程式執行效能至關重要。 Python 提供多線程(Multi-threading) 和多進程 (Multiprocessing)
Thumbnail
avatar
Karen
2023-08-15
[Python] 使用Threading模組在背景待命運行使用Python的Threading模組設計一個能夠在背景待命的程式,並在等待5秒後自動結束。我們將使用執行緒來執行背景任務,並使用定時等待來控制程式的結束時間。這種方法適用於不依賴於特定按鍵事件的情況,而是在固定的時間後自動退出程式。
avatar
Pochi
2023-06-24
[Python] 使用openpyxl寫入Excel文件在這篇教學中,我們將介紹如何使用Python的openpyxl套件將資料寫入Excel文件。openpyxl是一個功能強大的函式庫,可以讓我們輕鬆地處理Excel文件。
avatar
Pochi
2023-06-16
[Python] 使用openpyxl讀取Excel文件在這篇教學中,我們將介紹如何使用Python的openpyxl模組來讀取Excel文件中的資料。openpyxl是一個功能強大的函式庫,可以讓我們輕鬆地處理Excel文件。
avatar
Pochi
2023-06-16
[Python] 使用pyautogui來實作模擬鍵盤輸入安裝 pyautogui 在開始之前,我們需要先安裝 pyautogui 模塊。
avatar
Pochi
2023-06-08
[Python] 使用 OpenAI 的 ChatGPT API 實作聊天機器人這篇教學文章將介紹如何使用 OpenAI 的 GPT-3 模型來建立一個簡單的聊天機器人。
avatar
Pochi
2023-05-03
[Python] 使用pyautogui的滑鼠控制安裝 pyautogui 在開始之前,我們需要先安裝 pyautogui 模塊。你可以在終端或命令提示字元中輸入以下命令來安裝它: 1.移動滑鼠 2.模擬滑鼠點擊 3.模擬滑鼠拖曳 4.捲動滑鼠
avatar
Pochi
2023-04-26
[Python] 使用 pyautogui 套件來取得視窗 (windows)使用 pyautogui 套件來取得所有正在視窗 (windows)。
avatar
Pochi
2023-04-25
【Python】使用虛擬環境pipenv初玩python時常用pip安裝各式各樣的套件下來,而這些套件在本機中是以全域的方式安裝。假設今天需要接手別人的專案,所用的套件版本不相容,對於這些仰賴的套件(依賴dependencies)進行管理跟切分就成了一個課題。
Thumbnail
avatar
2022-06-06