在進行Python編程時,為了更好地了解程序的運行情況,調試及錯誤排查,我們需要使用日誌來記錄程序運行過程中的信息。Python提供了標準庫logging,可以很方便地輸出日誌信息,本文將對Python日誌輸出進行詳細闡述,從入門到實踐,教你如何讓你的代碼更好地顯示日誌信息。
一、Python日誌輸出基礎
Python的logging模塊提供了日誌記錄的功能。它可以輸出到終端、文件、郵件等,可讀性較高,同時可以更靈活地進行管理和控制。下面是一個簡單的例子:
“`
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug(‘This is a debug message’)
logging.info(‘This is an info message’)
logging.warning(‘This is a warning message’)
logging.error(‘This is an error message’)
logging.critical(‘This is a critical message’)
“`
運行上述代碼,會依次輸出不同級別的日誌信息:
“`
DEBUG:root:This is a debug message
INFO:root:This is an info message
WARNING:root:This is a warning message
ERROR:root:This is an error message
CRITICAL:root:This is a critical message
“`
上述代碼中,我們使用logging.basicConfig()配置了日誌的基本信息。level=logging.DEBUG表示將日誌等級設置為DEBUG,即輸出該等級及以上等級的日誌信息。除了DEBUG等級,還有INFO、WARNING、ERROR、CRITICAL等級。接着,我們使用logging.debug()、logging.info()等方法輸出不同等級的日誌信息。
另外,我們還可以通過設置format參數來控制輸出的格式,比如:
“`
import logging
logging.basicConfig(level=logging.DEBUG, format=’%(asctime)s – %(name)s – %(levelname)s – %(message)s’)
logger = logging.getLogger(__name__)
logger.debug(‘This is a debug message’)
logger.info(‘This is an info message’)
logger.warning(‘This is a warning message’)
logger.error(‘This is an error message’)
logger.critical(‘This is a critical message’)
“`
運行上述代碼,會按照設置的格式輸出日誌信息:
“`
2021-08-10 11:11:26,537 – __main__ – DEBUG – This is a debug message
2021-08-10 11:11:26,538 – __main__ – INFO – This is an info message
2021-08-10 11:11:26,538 – __main__ – WARNING – This is a warning message
2021-08-10 11:11:26,538 – __main__ – ERROR – This is an error message
2021-08-10 11:11:26,538 – __main__ – CRITICAL – This is a critical message
“`
在上述代碼中,我們設置format參數為’%(asctime)s – %(name)s – %(levelname)s – %(message)s’,其中’%(asctime)s’表示輸出時間,’%(name)s’表示輸出日誌所在模塊的名稱,’%(levelname)s’表示日誌等級,’%(message)s’表示輸出日誌信息。
二、Python日誌輸出高級配置
1. 使用配置文件進行配置
基本配置雖然簡單易懂,但靈活性不夠,無法滿足複雜的需求。此時我們可以使用配置文件進行配置。下面是一個配置文件的例子:
“`
[loggers]
keys=root,sampleLogger
[handlers]
keys=consoleHandler,fileHandler
[formatters]
keys=sampleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler,fileHandler
[logger_sampleLogger]
level=DEBUG
handlers=consoleHandler
qualname=sampleLogger
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=sampleFormatter
args=(sys.stdout,)
[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=sampleFormatter
args=(‘example.log’, ‘w’)
[formatter_sampleFormatter]
format=%(asctime)s – %(name)s – %(levelname)s – %(message)s
datefmt=%Y-%m-%d %H:%M:%S
“`
上述配置文件中,我們定義了三個部分:loggers、handlers、formatters。loggers定義了所有日誌器的名稱;handlers定義了所有處理器的名稱和類型;formatters定義了所有格式化器的名稱、格式化字符串和輸出日期格式。接着,我們定義了日誌器們和它們的屬性:level表示日誌的等級;handlers表示對應的處理器;qualname表示日誌器的名稱;propagate表示是否向上傳遞該日誌消息。最後,我們定義了兩個處理器和一個格式化器。
使用配置文件的方式可以使日誌的配置更加靈活,也更方便進行維護。使用方法如下:
“`
import logging.config
logging.config.fileConfig(‘logging.conf’)
logger = logging.getLogger(‘sampleLogger’)
logger.debug(‘This is a debug message’)
logger.info(‘This is an info message’)
logger.warning(‘This is a warning message’)
logger.error(‘This is an error message’)
logger.critical(‘This is a critical message’)
“`
運行上述代碼,會按照配置文件中定義的屬性輸出日誌信息。而對於項目較大的情況,在一個文件中定義格式化內容,並對多個模塊使用不同等級會更加便利。
2. 使用RotatingFileHandler進行日誌回滾
另一個常用的配置是日誌回滾。日誌文件佔用空間過大時,我們可以通過日誌回滾將舊的日誌文件進行刪除或壓縮。Python中提供了RotatingFileHandler來優雅地進行日誌回滾。下面是一個例子:
“`
import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(‘%(asctime)s – %(name)s – %(levelname)s – %(message)s’)
# 每個日誌文件最大的大小
maxBytes = 1024
# 最多保留的日誌文件數量
backupCount = 3
# 添加RotatingFileHandler
file_handler = RotatingFileHandler(‘example.log’, mode=’a’, maxBytes=maxBytes, backupCount=backupCount, encoding=None, delay=0)
file_handler.setFormatter(formatter)
file_handler.setLevel(logging.DEBUG)
logger.addHandler(file_handler)
# 輸出日誌信息
logger.debug(‘This is a debug message’)
logger.info(‘This is an info message’)
logger.warning(‘This is a warning message’)
logger.error(‘This is an error message’)
logger.critical(‘This is a critical message’)
“`
在上述代碼中,我們首先創建一個日誌器和formatter,並定義了日誌的等級和輸出格式。接着我們使用RotatingFileHandler創建文件處理器,並設置最大的日誌文件大小為1024位元組,並最多保留3個日誌文件。最後,我們將處理器加入到日誌器中,並使用日誌器輸出日誌信息。
三、Python日誌常用技巧
1. 輸出調用位置
在日誌輸出中,有時需要輸出日誌消息所在的源代碼行數、函數名和模塊名等調用位置信息,這時可以使用logging模塊提供的LogRecord屬性。下面是一個例子:
“`
import logging
logging.basicConfig(level=logging.DEBUG, format=’%(asctime)s – %(name)s – %(levelname)s – %(message)s – %(pathname)s:%(lineno)d’)
logger = logging.getLogger(__name__)
logger.debug(‘This is a debug message’)
“`
在上述代碼中,我們使用format參數設置了輸出日誌的格式,並添加了LogRecord屬性pathname、lineno,分別表示源代碼文件名和所在行號。運行上述代碼,輸出日誌消息以及調用位置信息。
2. 分模塊輸出日誌
在編程中,我們經常會使用多個模塊協同工作,為了更好地了解各個模塊的日誌信息,我們可以為每個模塊都創建一個日誌器,使用不同的日誌輸出方式和等級。例如:
“`
# main.py
import logging
import module1
import module2
logging.basicConfig(level=logging.DEBUG, format=’%(asctime)s – %(name)s – %(levelname)s – %(message)s’)
logger1 = logging.getLogger(‘module1’)
logger2 = logging.getLogger(‘module2’)
logger1.setLevel(logging.DEBUG)
logger2.setLevel(logging.WARNING)
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(logging.Formatter(‘%(asctime)s – %(name)s – %(levelname)s – %(message)s’))
logger1.addHandler(stream_handler)
file_handler = logging.FileHandler(‘module2.log’)
file_handler.setFormatter(logging.Formatter(‘%(asctime)s – %(name)s – %(name)s – %(levelname)s – %(message)s’))
logger2.addHandler(file_handler)
logger1.debug(‘debug message in module1’)
module1.func1()
logger2.warning(‘warning message in module2’)
module2.func2()
“`
在上述代碼中,我們在main.py中定義兩個日誌器logger1和logger2,並設置它們的不同等級和輸出方式。我們將’example.log’文件設為logger2的輸出文件,並添加輸出格式。
然後我們在module1.py和module2.py文件中定義了func1()和func2()函數,並分別輸出日誌信息。我們通過這種方式,可以為各個模塊設置不同的日誌等級和輸出方式,方便我們進行錯誤排查與修復。
結語
Python提供了強大的logging模塊,方便我們輸出日誌信息。我們可以通過logging模塊的基本使用、高級配置、常用技巧等多個方面,實現更為靈活、高效的日誌記錄。希望本文能對你在Python的編程工程中帶來幫助。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/277332.html