Python中如何實(shí)現(xiàn)日志記錄?日志文件如何按大小分割?

python中實(shí)現(xiàn)日志記錄主要依賴于Logging模塊。1. 首先導(dǎo)入logging模塊并配置日志級別、格式和輸出位置;2. 使用rotatingfilehandler按大小分割日志文件,設(shè)置最大文件大小和保留舊文件數(shù)量;3. 通過timedrotatingfilehandler按時(shí)間分割日志文件,可設(shè)定時(shí)間間隔和保留周期;4. 在線程/多進(jìn)程環(huán)境下,使用queuehandler和queuelistener避免競爭條件;5. 可通過yaml或json文件配置日志,提高靈活性和可維護(hù)性;自定義日志格式則通過formatter類實(shí)現(xiàn),支持多種占位符,并可根據(jù)需要擴(kuò)展實(shí)現(xiàn)更復(fù)雜邏輯。

Python中如何實(shí)現(xiàn)日志記錄?日志文件如何按大小分割?

python中實(shí)現(xiàn)日志記錄主要依賴于logging模塊,它可以靈活地配置日志級別、輸出位置和格式。日志文件按大小分割通常使用RotatingFileHandler或TimedRotatingFileHandler。

Python中如何實(shí)現(xiàn)日志記錄?日志文件如何按大小分割?

解決方案:

Python中如何實(shí)現(xiàn)日志記錄?日志文件如何按大小分割?

Python的logging模塊提供了強(qiáng)大的日志記錄功能。首先,你需要導(dǎo)入logging模塊,然后配置日志的基本設(shè)置,例如日志級別、日志格式和輸出位置。對于日志文件按大小分割,RotatingFileHandler是一個不錯的選擇。它允許你設(shè)置日志文件的最大大小和保留的舊日志文件數(shù)量。

立即學(xué)習(xí)Python免費(fèi)學(xué)習(xí)筆記(深入)”;

Python中如何實(shí)現(xiàn)日志記錄?日志文件如何按大小分割?

import logging from logging.handlers import RotatingFileHandler  # 配置日志記錄器 logger = logging.getLogger(__name__) logger.setLevel(logging.INFO)  # 創(chuàng)建一個RotatingFileHandler handler = RotatingFileHandler('my_log.log', maxBytes=1024*1024, backupCount=5) # 每個日志文件最大1MB,保留5個舊日志文件 handler.setLevel(logging.INFO)  # 創(chuàng)建一個格式化器 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter)  # 將handler添加到logger logger.addHandler(handler)  # 記錄一些日志 logger.info('This is an info message') logger.warning('This is a warning message') logger.error('This is an error message')

這段代碼創(chuàng)建了一個名為my_log.log的日志文件,當(dāng)它達(dá)到1MB時(shí),會自動創(chuàng)建一個新的日志文件,并保留最多5個舊日志文件。

如何自定義Python日志的格式?

自定義日志格式是通過logging.Formatter實(shí)現(xiàn)的。你可以使用各種占位符來定義日志消息的結(jié)構(gòu)。例如,%(asctime)s表示日志記錄的時(shí)間,%(name)s表示記錄器的名稱,%(levelname)s表示日志級別,%(message)s表示實(shí)際的日志消息。

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(module)s:%(lineno)d - %(message)s')

在這個例子中,我們添加了%(module)s(模塊名)和%(lineno)d(行號)到日志格式中。這在調(diào)試時(shí)非常有用,可以快速定位到產(chǎn)生日志的代碼位置。有時(shí)候,日志格式過于冗長反而不利于閱讀,需要根據(jù)實(shí)際情況調(diào)整。

除了字符串格式化,還可以自定義Formatter類,實(shí)現(xiàn)更復(fù)雜的邏輯,例如根據(jù)日志級別改變顏色。這需要繼承logging.Formatter類,并重寫format方法。

如何根據(jù)時(shí)間分割Python日志文件?

除了按大小分割日志文件,按時(shí)間分割也是一個常見的需求。TimedRotatingFileHandler可以滿足這個需求。它可以根據(jù)指定的時(shí)間間隔(例如每天、每周)自動創(chuàng)建新的日志文件。

import logging from logging.handlers import TimedRotatingFileHandler import datetime  # 創(chuàng)建一個TimedRotatingFileHandler handler = TimedRotatingFileHandler('my_log.log', when="midnight", interval=1, backupCount=7) # 每天凌晨創(chuàng)建一個新的日志文件,保留7天的日志 handler.suffix = "%Y%m%d" # 日志文件名的后綴 handler.extMatch = re.compile(r"^d{8}$")  # 創(chuàng)建一個格式化器 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter)  # 將handler添加到logger logger.addHandler(handler)  # 記錄一些日志 logger.info('This is an info message') logger.warning('This is a warning message') logger.error('This is an error message')

在這個例子中,when=”midnight”表示每天凌晨創(chuàng)建一個新的日志文件,interval=1表示間隔為1天,backupCount=7表示保留7天的日志。handler.suffix = “%Y%m%d”定義了日志文件名的后綴格式,例如my_log.log.20231027。需要注意的是,如果沒有設(shè)置handler.extMatch,舊的日志文件可能不會被正確刪除。

如何處理多線程/多進(jìn)程環(huán)境下的Python日志記錄?

在多線程或多進(jìn)程環(huán)境下,日志記錄可能會出現(xiàn)競爭條件,導(dǎo)致日志消息丟失或損壞。為了解決這個問題,可以使用QueueHandler和QueueListener。QueueHandler將日志消息放入一個隊(duì)列中,QueueListener從隊(duì)列中取出消息并將其寫入日志文件。

import logging import logging.handlers import multiprocessing import queue  # 創(chuàng)建一個隊(duì)列 log_queue = queue.Queue(-1)  # 配置日志記錄器 logger = logging.getLogger(__name__) logger.setLevel(logging.INFO)  # 創(chuàng)建一個QueueHandler queue_handler = logging.handlers.QueueHandler(log_queue) logger.addHandler(queue_handler)  # 定義一個日志監(jiān)聽器 def worker_process(log_queue):     listener = logging.handlers.QueueListener(log_queue, logging.FileHandler('my_log.log'))     listener.start()     listener.stop()  # 創(chuàng)建一個進(jìn)程 process = multiprocessing.Process(target=worker_process, args=(log_queue,)) process.start()  # 記錄一些日志 logger.info('This is an info message from main process')  # 在子進(jìn)程中記錄日志 def log_from_child():     logger = logging.getLogger(__name__)     logger.info('This is an info message from child process')  child_process = multiprocessing.Process(target=log_from_child) child_process.start() child_process.join()  process.join()

這個例子創(chuàng)建了一個隊(duì)列,并將日志消息放入隊(duì)列中。然后,創(chuàng)建了一個進(jìn)程來監(jiān)聽隊(duì)列,并將消息寫入日志文件。這樣可以避免多線程/多進(jìn)程環(huán)境下的競爭條件。需要注意的是,QueueListener需要在主進(jìn)程退出前停止,否則可能會導(dǎo)致程序阻塞。

如何使用YAML或JSON文件配置Python日志?

logging.config模塊允許你使用YAML或JSON文件來配置日志記錄器。這使得配置更加靈活和可維護(hù)。

import logging.config import yaml  # 從YAML文件加載配置 with open('logging.yaml', 'r') as f:     config = yaml.safe_load(f)     logging.config.dictConfig(config)  # 獲取日志記錄器 logger = logging.getLogger(__name__)  # 記錄一些日志 logger.info('This is an info message')

logging.yaml文件的內(nèi)容如下:

version: 1 formatters:   simple:     format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s' handlers:   console:     class: logging.StreamHandler     level: DEBUG     formatter: simple     stream: ext://sys.stdout   file:     class: logging.handlers.RotatingFileHandler     level: INFO     formatter: simple     filename: my_log.log     maxBytes: 10485760 # 10MB     backupCount: 5 root:   level: INFO   handlers: [console, file] disable_existing_loggers: False

這種方式使得日志配置更加清晰,方便修改和維護(hù)。你可以根據(jù)需要調(diào)整YAML文件中的參數(shù),例如日志級別、格式和輸出位置,而無需修改代碼。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊8 分享