最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python logging模塊詳細(xì)教程與最佳實(shí)踐

 更新時間:2026年01月27日 10:31:59   作者:cuber膜拜  
本文詳細(xì)介紹了Python的logging模塊,從基礎(chǔ)概念到高級用法,包括日志級別、格式、處理器、記錄器等通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

Python logging模塊完整教程

Python的logging模塊是標(biāo)準(zhǔn)庫中強(qiáng)大而靈活的日志記錄工具,它能夠幫助開發(fā)者記錄應(yīng)用程序運(yùn)行過程中的各種事件和信息。通過本教程,您將從基礎(chǔ)概念開始,逐步學(xué)習(xí)如何配置、使用和優(yōu)化日志系統(tǒng),最終掌握在實(shí)際項(xiàng)目中應(yīng)用logging模塊的各種技巧。本教程涵蓋了從簡單的日志輸出到高級的日志配置和性能優(yōu)化的完整內(nèi)容。

什么是 Python logging

Python logging模塊是Python標(biāo)準(zhǔn)庫的一部分,提供了一個靈活的框架來記錄應(yīng)用程序運(yùn)行時的各種事件和信息。

核心特點(diǎn)

  • 層次化日志系統(tǒng): 支持多個logger形成層次結(jié)構(gòu)
  • 多種日志級別: DEBUG、INFO、WARNING、ERROR、CRITICAL
  • 靈活的輸出目標(biāo): 控制臺、文件、網(wǎng)絡(luò)等
  • 可配置的格式: 自定義日志消息格式
  • 線程安全: 支持多線程環(huán)境
  • 性能優(yōu)化: 支持異步日志處理

快速開始

學(xué)習(xí)建議
建議先跟著這個例子動手實(shí)踐,理解基本流程后再深入學(xué)習(xí)細(xì)節(jié)。

Hello World 示例

import logging
# 基本的日志記錄
logging.debug("這是一條調(diào)試信息")
logging.info("這是一條信息")
logging.warning("這是一條警告")
logging.error("這是一條錯誤")
logging.critical("這是一條嚴(yán)重錯誤")

代碼說明

  1. import logging: 導(dǎo)入logging模塊
  2. logging.debug(): 記錄調(diào)試級別信息
  3. logging.info(): 記錄普通信息
  4. logging.warning(): 記錄警告信息
  5. logging.error(): 記錄錯誤信息
  6. logging.critical(): 記錄嚴(yán)重錯誤信息

運(yùn)行結(jié)果

WARNING:root:這是一條警告
ERROR:root:這是一條錯誤
CRITICAL:root:這是一條嚴(yán)重錯誤

代碼解析

  • 默認(rèn)配置: 默認(rèn)情況下,只有WARNING及以上級別的日志會被顯示
  • 默認(rèn)格式: [級別]:[logger名稱]:[消息]
  • 默認(rèn)輸出: 默認(rèn)輸出到stderr(標(biāo)準(zhǔn)錯誤流)

[!question] 為什么要這樣寫?
logging模塊的默認(rèn)配置相對保守,只顯示W(wǎng)ARNING級別的日志。這是因?yàn)檫^多的日志信息可能會干擾程序的主要輸出,同時日志系統(tǒng)的開銷也應(yīng)該被控制。

[!bug] 如果沒有看到DEBUG和INFO日志
這是正常的!logging默認(rèn)只顯示W(wǎng)ARNING及以上級別的日志。要顯示所有級別的日志,需要配置logging級別。

核心概念

概念1:Logger(記錄器)

定義: Logger是日志系統(tǒng)的核心組件,用于創(chuàng)建和記錄日志消息。

為什么重要: Logger為應(yīng)用程序提供了記錄日志的入口點(diǎn),它決定了哪些級別的消息會被記錄,以及消息應(yīng)該發(fā)送到哪里。

工作原理:
Logger創(chuàng)建后會被分配一個名稱和日志級別。當(dāng)調(diào)用logger的日志方法時,會檢查消息的級別是否高于或等于logger的級別,如果是則處理該消息。

示例

import logging
# 創(chuàng)建logger
logger = logging.getLogger('my_app')
logger.setLevel(logging.DEBUG)
# 記錄日志
logger.debug("調(diào)試消息")
logger.info("信息消息")
logger.warning("警告消息")

[!note] 深入理解

  • Logger名稱通常采用點(diǎn)分格式,如’my_app.database’
  • 同一個名稱的logger返回的是同一個實(shí)例
  • 如果不設(shè)置級別,會繼承父logger的級別

概念2:Handler(處理器)

定義: Handler負(fù)責(zé)將日志消息發(fā)送到目標(biāo)位置,如控制臺、文件、網(wǎng)絡(luò)等。

為什么重要: Handler決定了日志的最終去向,是實(shí)現(xiàn)日志系統(tǒng)靈活性的關(guān)鍵。

工作原理:
每個Logger可以附加多個Handler。當(dāng)Logger記錄消息時,會將消息傳遞給所有附加的Handler,每個Handler根據(jù)其配置獨(dú)立處理消息。

示例

import logging
# 創(chuàng)建logger
logger = logging.getLogger('my_app')
logger.setLevel(logging.DEBUG)
# 控制臺handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 文件handler
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.DEBUG)
# 添加handler
logger.addHandler(console_handler)
logger.addHandler(file_handler)
# 記錄日志
logger.debug("只記錄到文件")
logger.info("同時記錄到控制臺和文件")

[!note] 深入理解

  • 一個Logger可以關(guān)聯(lián)多個Handler
  • 每個Handler可以有自己的日志級別和格式
  • 可以通過Handler實(shí)現(xiàn)日志過濾、分發(fā)等功能

概念3:Formatter(格式化器)

定義: Formatter定義了日志消息的輸出格式。

為什么重要: 好的日志格式能夠使日志信息更加清晰、易讀,便于問題排查。

工作原理:
Formatter將日志事件對象轉(zhuǎn)換為字符串??梢宰远x包含時間戳、日志級別、logger名稱、消息等字段。

示例

import logging
# 創(chuàng)建formatter
formatter = logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# 創(chuàng)建handler并設(shè)置formatter
handler = logging.StreamHandler()
handler.setFormatter(formatter)
# 使用handler
logger = logging.getLogger('my_app')
logger.addHandler(handler)
# 記錄日志
logger.info("格式化的日志消息")

輸出

2024-01-01 12:00:00,123 - my_app - INFO - 格式化的日志消息

[!note] 深入理解

  • %(asctime)s: 時間戳
  • %(name)s: logger名稱
  • %(levelname)s: 日志級別
  • %(message)s: 日志消息
  • 可以添加更多字段,如文件名、行號、函數(shù)名等

概念之間的關(guān)系

Logger作為入口點(diǎn),通過日志級別控制哪些消息會被記錄。Logger可以關(guān)聯(lián)多個Handler,每個Handler可以有自己的Formatter來格式化輸出。這樣實(shí)現(xiàn)了日志系統(tǒng)的靈活配置。

基礎(chǔ)功能詳解

功能1:日志級別

用途: 控制哪些信息應(yīng)該被記錄,幫助過濾日志信息。

基本語法

logging.debug("消息")      # 調(diào)試級別
logging.info("消息")       # 信息級別
logging.warning("消息")     # 警告級別
logging.error("消息")       # 錯誤級別
logging.critical("消息")   # 嚴(yán)重錯誤級別

參數(shù)說明

  • message: 日志消息字符串,可以包含格式化占位符

簡單示例

import logging
# 設(shè)置日志級別
logging.basicConfig(level=logging.DEBUG)
logging.debug("調(diào)試信息:程序開始執(zhí)行")
logging.info("信息:加載配置文件")
logging.warning("警告:配置文件版本可能過時")
logging.error("錯誤:無法連接到數(shù)據(jù)庫")
logging.critical("嚴(yán)重錯誤:系統(tǒng)即將崩潰")

常見用法

import logging
# 獲取logger
logger = logging.getLogger('app')
# 設(shè)置日志級別
logger.setLevel(logging.INFO)  # 只記錄INFO及以上級別
# 針對不同級別有不同處理
if some_critical_condition:
    logger.critical("關(guān)鍵問題發(fā)生,需要立即處理")
elif some_error_condition:
    logger.error("發(fā)生錯誤,影響功能正常運(yùn)行")
else:
    logger.info("系統(tǒng)運(yùn)行正常")

[!tip] 最佳實(shí)踐

  • 在開發(fā)環(huán)境中使用DEBUG級別記錄詳細(xì)信息
  • 在生產(chǎn)環(huán)境中使用INFO或WARNING級別避免日志過多
  • 根據(jù)重要性選擇合適的日志級別

[!warning] 常見陷阱

  • 不要過度使用DEBUG級別,否則會產(chǎn)生大量無用日志
  • 避免在循環(huán)中頻繁記錄INFO級別日志,影響性能
  • 確保錯誤信息包含足夠的上下文信息

功能2:基本配置

用途: 快速配置logging系統(tǒng)的基本參數(shù)。

基本語法

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    filename='app.log',
    filemode='a'
)

參數(shù)說明

  • level: 日志級別閾值
  • format: 日志消息格式
  • filename: 日志文件名
  • filemode: 文件打開模式('w’覆蓋,'a’追加)
  • datefmt: 日期時間格式
  • style: 格式樣式(‘%’, ‘{’, ‘$’)
  • force: 是否重新配置已經(jīng)存在的logging

簡單示例

import logging
# 基本配置
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename='my_app.log',
    filemode='a'
)
# 現(xiàn)在所有日志都會寫入文件
logging.debug("調(diào)試信息")
logging.info("信息")

常見用法

import logging
# 生產(chǎn)環(huán)境配置
logging.basicConfig(
    level=logging.WARNING,
    format='%(asctime)s [%(levelname)s] %(message)s',
    filename='production.log'
)
# 開發(fā)環(huán)境配置
import sys
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(name)s %(levelname)s: %(message)s',
    stream=sys.stdout  # 輸出到控制臺
)

[!tip] 最佳實(shí)踐

  • 在程序入口處進(jìn)行一次basicConfig配置
  • 根據(jù)環(huán)境(開發(fā)/測試/生產(chǎn))調(diào)整日志級別
  • 使用不同的輸出目標(biāo)(控制臺/文件)進(jìn)行調(diào)試

[[文件操作]]

功能3:Logger創(chuàng)建和使用

用途: 創(chuàng)建和管理應(yīng)用程序的logger實(shí)例。

基本語法

logger = logging.getLogger('logger_name')
logger.debug("消息")

參數(shù)說明

  • logger_name: logger的名稱,建議使用模塊名或類名

簡單示例

import logging
# 創(chuàng)建不同模塊的logger
db_logger = logging.getLogger('my_app.database')
web_logger = logging.getLogger('my_app.web')
user_logger = logging.getLogger('my_app.user')
# 配置logger級別
db_logger.setLevel(logging.DEBUG)
web_logger.setLevel(logging.INFO)
user_logger.setLevel(logging.WARNING)
# 記錄日志
db_logger.debug("數(shù)據(jù)庫連接建立")
db_logger.info("執(zhí)行SQL查詢")
web_logger.info("收到HTTP請求")
user_logger.warning("用戶嘗試訪問無權(quán)限的頁面")

常見用法

import logging
import os
# 基于模塊名創(chuàng)建logger
logger = logging.getLogger(__name__)
# 如果logger還沒有配置,進(jìn)行基本配置
if not logger.handlers:
    handler = logging.StreamHandler()
    formatter = logging.Formatter(
        '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
    )
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    logger.setLevel(logging.INFO)
# 使用logger
logger.debug("Debug message")
logger.info("App started")
logger.error("Failed to process request")

[!tip] 最佳實(shí)踐

  • 使用__name__作為logger名稱,這樣能清楚地知道日志來源
  • 每個模塊創(chuàng)建自己的logger實(shí)例
  • 避免直接使用logging模塊的函數(shù),而是使用logger實(shí)例

功能4:Handler配置

用途: 配置日志輸出的目標(biāo)位置和方式。

基本語法

# StreamHandler - 輸出到控制臺
console_handler = logging.StreamHandler()
# FileHandler - 輸出到文件
file_handler = logging.FileHandler('app.log')
# RotatingFileHandler - 輪轉(zhuǎn)文件
from logging.handlers import RotatingFileHandler
rotating_handler = RotatingFileHandler(
    'app.log',
    maxBytes=1024*1024,  # 1MB
    backupCount=5
)
# TimedRotatingFileHandler - 按時間輪轉(zhuǎn)
from logging.handlers import TimedRotatingFileHandler
timed_handler = TimedRotatingFileHandler(
    'app.log',
    when='midnight',
    backupCount=7
)

參數(shù)說明

  • StreamHandler: 流處理器,可以指定輸出流(默認(rèn)是stderr)
  • FileHandler: 文件處理器
  • maxBytes: 文件最大大?。≧otatingFileHandler)
  • backupCount: 保留的備份文件數(shù)
  • when: 輪轉(zhuǎn)時間間隔(TimedRotatingFileHandler)

簡單示例

import logging
from logging.handlers import RotatingFileHandler
# 創(chuàng)建logger
logger = logging.getLogger('app')
logger.setLevel(logging.DEBUG)
# 控制臺handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 文件handler
file_handler = RotatingFileHandler(
    'app.log',
    maxBytes=1024*1024,  # 1MB
    backupCount=3,
    encoding='utf-8'
)
file_handler.setLevel(logging.DEBUG)
# 添加handler
logger.addHandler(console_handler)
logger.addHandler(file_handler)
# 測試日志
logger.debug("這是調(diào)試信息,只記錄到文件")
logger.info("這是信息,同時記錄到控制臺和文件")

常見用法

import logging
import sys
from logging.handlers import SMTPHandler
# 配置多輸出
logger = logging.getLogger('my_app')
# 控制臺輸出
console = logging.StreamHandler(sys.stdout)
console.setLevel(logging.INFO)
console_format = logging.Formatter('%(levelname)s: %(message)s')
console.setFormatter(console_format)
# 文件輸出
file_handler = logging.FileHandler('app.log')
file_handler.setLevel(logging.DEBUG)
file_format = logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
file_handler.setFormatter(file_format)
# 郵件handler(僅用于嚴(yán)重錯誤)
mail_handler = SMTPHandler(
    mailhost=('smtp.example.com', 587),
    fromaddr='app@example.com',
    toaddrs=['admin@example.com'],
    subject='Application Error',
    credentials=('username', 'password'),
    secure=()
)
mail_handler.setLevel(logging.CRITICAL)
# 添加handler
logger.addHandler(console)
logger.addHandler(file_handler)
logger.addHandler(mail_handler)

[!tip] 最佳實(shí)踐

  • 為不同的日志級別使用不同的輸出渠道
  • 生產(chǎn)環(huán)境中配置適當(dāng)?shù)妮嗈D(zhuǎn)策略,避免日志文件過大
  • 使用不同的格式滿足不同的輸出需求

[[異常處理]]
[[Python基礎(chǔ)語法]]

實(shí)踐項(xiàng)目

[!example] 項(xiàng)目目標(biāo)
通過構(gòu)建一個簡單的Web服務(wù)器日志系統(tǒng),綜合運(yùn)用前面學(xué)到的logging知識。

項(xiàng)目需求

  • 記錄HTTP請求信息
  • 根據(jù)請求狀態(tài)分類日志級別
  • 實(shí)現(xiàn)日志輪轉(zhuǎn)和歸檔
  • 支持多種輸出格式

項(xiàng)目結(jié)構(gòu)

web_logger/
├── main.py
├── logger_config.py
├── requirements.txt
└── logs/
    └── app.log

實(shí)現(xiàn)步驟

步驟1:創(chuàng)建日志配置模塊

目標(biāo):創(chuàng)建一個可復(fù)用的日志配置模塊。

代碼

# logger_config.py
import logging
import logging.handlers
import os
from datetime import datetime
class WebLoggerConfig:
    def __init__(self, log_dir='logs'):
        self.log_dir = log_dir
        self.logger = logging.getLogger('web_server')
        self._setup_logger()
    def _setup_logger(self):
        # 確保日志目錄存在
        os.makedirs(self.log_dir, exist_ok=True)
        # 設(shè)置logger級別
        self.logger.setLevel(logging.DEBUG)
        # 清除現(xiàn)有的handler
        self.logger.handlers.clear()
        # 創(chuàng)建formatter
        detailed_formatter = logging.Formatter(
            '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        )
        # 控制臺handler
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        console_handler.setFormatter(detailed_formatter)
        # 文件handler - 主日志
        file_handler = logging.handlers.RotatingFileHandler(
            os.path.join(self.log_dir, 'app.log'),
            maxBytes=10*1024*1024,  # 10MB
            backupCount=5,
            encoding='utf-8'
        )
        file_handler.setLevel(logging.DEBUG)
        file_handler.setFormatter(detailed_formatter)
        # 錯誤日志handler
        error_handler = logging.handlers.RotatingFileHandler(
            os.path.join(self.log_dir, 'error.log'),
            maxBytes=5*1024*1024,  # 5MB
            backupCount=3,
            encoding='utf-8'
        )
        error_handler.setLevel(logging.ERROR)
        error_handler.setFormatter(detailed_formatter)
        # 添加所有handler
        self.logger.addHandler(console_handler)
        self.logger.addHandler(file_handler)
        self.logger.addHandler(error_handler)
    def get_logger(self):
        return self.logger

解釋

  • 創(chuàng)建了WebLoggerConfig類來管理日志配置
  • 實(shí)現(xiàn)了多級日志輸出(控制臺、主文件、錯誤文件)
  • 使用RotatingFileHandler實(shí)現(xiàn)日志輪轉(zhuǎn)
  • 錯誤日志單獨(dú)記錄,便于問題排查
步驟2:創(chuàng)建主應(yīng)用程序

目標(biāo):模擬Web服務(wù)器處理HTTP請求并記錄日志。

代碼

# main.py
from logger_config import WebLoggerConfig
import random
import time
from datetime import datetime
# 初始化日志系統(tǒng)
logger_config = WebLoggerConfig()
logger = logger_config.get_logger()
def simulate_web_request(request_id):
    """模擬處理HTTP請求"""
    logger.info(f"收到請求 #{request_id}")
    # 模擬請求處理時間
    process_time = random.uniform(0.1, 2.0)
    time.sleep(process_time)
    # 模擬不同的響應(yīng)狀態(tài)
    status_code = random.choices(
        [200, 404, 500],
        weights=[0.8, 0.15, 0.05]
    )[0]
    # 記錄處理結(jié)果
    if status_code == 200:
        logger.debug(f"請求 #{request_id} 處理成功,耗時: {process_time:.2f}s")
        logger.info(f"響應(yīng) #{request_id}: {status_code} OK")
        return "OK"
    elif status_code == 404:
        logger.warning(f"請求 #{request_id}: 404 Not Found - 資源不存在")
        return "Not Found"
    else:
        logger.error(f"請求 #{request_id} 處理失敗,錯誤代碼: {status_code}")
        logger.error(f"詳細(xì)信息: 服務(wù)器內(nèi)部錯誤")
        return "Internal Server Error"
def main():
    """主程序"""
    logger.info("Web服務(wù)器啟動")
    logger.info("開始處理請求...")
    try:
        # 模擬處理100個請求
        for i in range(1, 101):
            result = simulate_web_request(i)
            # 每10個請求輸出統(tǒng)計信息
            if i % 10 == 0:
                logger.info(f"已處理 {i} 個請求")
    except KeyboardInterrupt:
        logger.warning("收到中斷信號,正在關(guān)閉服務(wù)器...")
    except Exception as e:
        logger.critical(f"服務(wù)器發(fā)生嚴(yán)重錯誤: {str(e)}", exc_info=True)
    finally:
        logger.info("Web服務(wù)器關(guān)閉")
if __name__ == "__main__":
    main()

解釋

  • 使用WebLoggerConfig獲取配置好的logger
  • 實(shí)現(xiàn)了模擬HTTP請求處理的函數(shù)
  • 根據(jù)響應(yīng)狀態(tài)碼使用不同的日志級別
  • 添加了異常處理和程序生命周期日志

完整代碼

項(xiàng)目的完整代碼包含兩個文件:

  1. logger_config.py - 日志配置模塊
  2. main.py - 主應(yīng)用程序

運(yùn)行和測試

# 安裝依賴(這個項(xiàng)目不需要額外依賴)
pip install -r requirements.txt
# 運(yùn)行程序
python main.py

預(yù)期輸出

2024-01-01 10:00:00,123 [INFO] web_server: Web服務(wù)器啟動
2024-01-01 10:00:00,124 [INFO] web_server: 開始處理請求...
2024-01-01 10:00:00,125 [INFO] web_server: 收到請求 #1
2024-01-01 10:00:01,321 [INFO] web_server: 響應(yīng) #1: 200 OK
2024-01-01 10:00:01,322 [INFO] web_server: 收到請求 #2
2024-01-01 10:00:02,456 [WARNING] web_server: 請求 #2: 404 Not Found - 資源不存在
...
2024-01-01 10:00:15,789 [INFO] web_server: 已處理 10 個請求
...

檢查logs目錄下的日志文件,可以看到:

  • app.log - 包含所有日志
  • error.log - 只包含ERROR級別的日志

進(jìn)階主題

主題1:自定義日志級別

什么時候需要: 當(dāng)內(nèi)置的日志級別不足以滿足業(yè)務(wù)需求時,如需要區(qū)分不同類型的警告。

深入理解:
Python logging允許創(chuàng)建自定義的日志級別,這樣可以根據(jù)業(yè)務(wù)需求定義更細(xì)粒度的日志分類。自定義級別需要定義級別數(shù)值和級別名稱。

高級示例

import logging
# 定義自定義級別
logging.addLevelName(35, "TRACE")  # 比DEBUG更低的級別
logging.addLevelName(45, "NOTICE")  # 介于INFO和WARNING之間
def trace(self, message, *args, **kwargs):
    """TRACE級別方法"""
    if self.isEnabledFor(35):
        self._log(35, message, args, **kwargs)
def notice(self, message, *args, **kwargs):
    """NOTICE級別方法"""
    if self.isEnabledFor(45):
        self._log(45, message, args, **kwargs)
# 添加方法到Logger類
logging.Logger.trace = trace
logging.Logger.notice = notice
# 使用自定義級別
logger = logging.getLogger('app')
logger.trace("詳細(xì)的跟蹤信息")
logger.debug("調(diào)試信息")
logger.notice("需要注意的事項(xiàng)")
logger.info("常規(guī)信息")

性能考慮:

  • 自定義級別會增加系統(tǒng)開銷
  • 合理設(shè)置級別數(shù)值,避免與現(xiàn)有級別沖突
  • 考慮業(yè)務(wù)需求是否真的需要額外的級別

主題2:上下文感知的日志

什么時候需要: 需要在日志中包含請求ID、用戶ID等上下文信息時。

深入理解:
通過使用logger的adapter功能,可以輕松地為所有日志消息添加上下文信息,這樣在分布式系統(tǒng)中可以追蹤完整的請求鏈路。

高級示例

import logging
class ContextAdapter(logging.LoggerAdapter):
    """帶上下文的Logger適配器"""
    def __init__(self, logger, extra=None):
        super().__init__(logger, extra or {})
    def process(self, msg, kwargs):
        # 為每條消息添加上下文
        kwargs['extra'] = kwargs.get('extra', {})
        kwargs['extra'].update(self.extra)
        return msg, kwargs
# 使用示例
logger = logging.getLogger('web_service')
adapter = ContextAdapter(logger, {
    'request_id': 'req-12345',
    'user_id': 'user-67890',
    'ip_address': '192.168.1.1'
})
# 記錄日志
adapter.info("用戶登錄成功")
adapter.error("數(shù)據(jù)庫連接失敗")
# 輸出示例:
# 2024-01-01 12:00:00 [INFO] web_service: 用戶登錄成功
#   request_id=req-12345 user_id=user-67890 ip_address=192.168.1.1

性能考慮:

  • 上下文信息會占用內(nèi)存
  • 避免在上下文中存儲大量數(shù)據(jù)
  • 考慮使用線程局部變量存儲上下文

主題3:異步日志

什么時候需要: 在高并發(fā)環(huán)境下,同步日志記錄可能成為性能瓶頸時。

深入理解:
異步日志通過后臺線程處理日志寫入,避免阻塞主線程。Python 3.7+的logging模塊內(nèi)置了QueueHandler和QueueListener來實(shí)現(xiàn)異步日志。

高級示例

import logging
import logging.handlers
import queue
import time
from threading import Thread
class AsyncLogging:
    def __init__(self):
        self.log_queue = queue.Queue(-1)  # 無限隊(duì)列
        self.setup_logger()
    def setup_logger(self):
        # 配置logger
        logger = logging.getLogger('async_app')
        logger.setLevel(logging.DEBUG)
        # 創(chuàng)建QueueHandler
        queue_handler = logging.handlers.QueueHandler(self.log_queue)
        logger.addHandler(queue_handler)
        # 創(chuàng)建QueueListener
        file_handler = logging.FileHandler('async_app.log')
        file_handler.setFormatter(logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s'
        ))
        # 啟動監(jiān)聽器線程
        self.listener = logging.handlers.QueueListener(
            self.log_queue,
            file_handler,
            respect_handler_level=True
        )
        self.listener.start()
        # 保存logger
        self.logger = logger
    def stop(self):
        """停止異步日志"""
        self.logger.info("正在關(guān)閉異步日志系統(tǒng)")
        self.listener.stop()
    def get_logger(self):
        return self.logger
# 使用異步日志
async_logger = AsyncLogging()
logger = async_logger.get_logger()
# 模擬高并發(fā)場景
def worker(worker_id):
    for i in range(10):
        logger.info(f"Worker {worker_id} 處理任務(wù) {i}")
        time.sleep(0.1)
# 創(chuàng)建多個線程
threads = []
for i in range(5):
    t = Thread(target=worker, args=(i,))
    threads.append(t)
    t.start()
# 等待所有線程完成
for t in threads:
    t.join()
# 停止異步日志
async_logger.stop()

性能考慮:

  • 異步日志會增加內(nèi)存使用(隊(duì)列)
  • 需要合理設(shè)置隊(duì)列大小,避免內(nèi)存溢出
  • 程序退出時需要正確關(guān)閉監(jiān)聽器
  • 在高吞吐量場景下,異步日志能顯著提升性能

主題4:結(jié)構(gòu)化日志

什么時候需要: 需要將日志數(shù)據(jù)發(fā)送到日志分析系統(tǒng)(如ELK Stack)時。

深入理解:
結(jié)構(gòu)化日志使用JSON等格式記錄日志,便于日志解析和分析。Python 3.9+的logging模塊支持直接輸出JSON格式的日志。

高級示例

import logging
import json
from datetime import datetime
class JSONFormatter(logging.Formatter):
    """JSON格式的日志格式化器"""
    def format(self, record):
        log_data = {
            'timestamp': datetime.fromtimestamp(record.created).isoformat(),
            'level': record.levelname,
            'logger': record.name,
            'message': record.getMessage(),
            'module': record.module,
            'function': record.funcName,
            'line': record.lineno,
            'thread': record.thread,
            'process': record.process
        }
        # 添加異常信息
        if record.exc_info:
            log_data['exception'] = self.formatException(record.exc_info)
        # 添加額外的字段
        if hasattr(record, 'extra_data'):
            log_data.update(record.extra_data)
        return json.dumps(log_data, ensure_ascii=False)
# 配置結(jié)構(gòu)化日志
logger = logging.getLogger('structured')
logger.setLevel(logging.DEBUG)
# 文件handler
file_handler = logging.FileHandler('structured.log')
file_handler.setFormatter(JSONFormatter())
# 控制臺handler
console_handler = logging.StreamHandler()
console_handler.setFormatter(logging.Formatter(
    '%(levelname)s: %(message)s'
))
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 記錄結(jié)構(gòu)化日志
logger.info("用戶登錄", extra={
    'user_id': '12345',
    'ip': '192.168.1.1',
    'device': 'mobile'
})
logger.error("數(shù)據(jù)庫操作失敗", exc_info=True)

輸出示例(JSON)

{
  "timestamp": "2024-01-01T12:00:00.123456",
  "level": "INFO",
  "logger": "structured",
  "message": "用戶登錄",
  "module": "main",
  "function": "main",
  "line": 42,
  "thread": 12345,
  "process": 67890,
  "user_id": "12345",
  "ip": "192.168.1.1",
  "device": "mobile"
}

到此這篇關(guān)于Python logging模塊詳細(xì)教程與最佳實(shí)踐的文章就介紹到這了,更多相關(guān)Python logging模塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

墨玉县| 七台河市| 岳普湖县| 公安县| 古浪县| 通山县| 赣榆县| 霍城县| 海阳市| 井陉县| 天柱县| 昌乐县| 丰镇市| 大英县| 定南县| 都安| 安义县| 申扎县| 临沧市| 高碑店市| 赤峰市| 合肥市| 竹山县| 罗江县| 黔西| 三亚市| 苗栗县| 柳林县| 沈阳市| 新晃| 横山县| 建始县| 乌鲁木齐市| 贞丰县| 汝阳县| 嘉兴市| 裕民县| 丰台区| 公安县| 玛纳斯县| 安义县|