小編寫這篇文章的主要目的,就是給大家介紹下關于在Python中,有內置的logging,那么,我們在進行使用它的時候,有什么使用方法呢?下面就給大家詳細介紹。
logging的主要作用
它的作用是給日志記錄的接口和眾多處理模塊,供用戶存儲各種格式的日志,幫助調試程序或者記錄程序運行過程中的輸出信息。
logging日志等級
logging日志等級分為五個等級,優先級從高到低依次是:
**CRITICAL;**程序嚴重錯誤
**ERROR;**程序錯誤/部分功能錯誤
**WARNING;**程序有發生錯誤的可能
**INFO;**程序正常運行時的信息
DEBUG程序調試信息
默認的日志的記錄等級為WARNING,即當日志的等級大于獲等于WARNING時才會被記錄。
一般常用的記錄等級為INFO,其用于記錄程序的正常運行的一些信息(類似于print)。
當日志的等級達到WARNING以上時,表明此時程序不能正常運行;
logging的基礎函數
logging.basicConfig(**kwargs)
在沒有顯式的進行創建記錄器(logger)時,會默認創建一個root logger,而logging.basicConfig(**kwargs)可以創建帶有默認的Formatter的streamHandle并將其添加到根日志記錄器中來初始化基本配置。
比如
import logging logging.debug('Debug code!') logging.info('Run code!') logging.warning('Watch out!') logging.error('This is an error') logging.critical('This is a ciritical')
上面代碼中logging并沒有顯式的創建logger(logging.getLogger),其在直接使用debug(),info(),warning(),error(),critical()時會使用默認的root logger,并會自動調用自定義的或者默認的logging.basicConfig(**kwargs)初始化root logger。
自定義的logging.basicConfig(**kwargs)中的參數有以下的主要的選項:
例如下面通過自定義logging.basicConfig(**kwargs)來初始化root logger來獲得DEBUG級別及以上的日志記錄并保存到log.txt文件中。
import logging logging.basicConfig(filename='./log.txt', format='%(asctime)s-%(name)s-%(levelname)s-%(message)s-%(funcName)s:%(lineno)d', level=logging.DEBUG) logging.debug('Debug code!') logging.info('Run code!') logging.warning('Watch out!') logging.error('This is an error') logging.critical('This is a ciritical')
logging的四大組件(類)
Logger
除了根記錄器(root logger)外,最主要的是可以自己創建日志記錄器。
通過模塊級別的函數logging.getLogger(name)實例化記錄器
默認情況下,記錄器采用層級結構,通過.來區分不同的層級。比如有個名叫foo的記錄器則foo.a和foo.b都是foo的子級記錄器。當然,最開始的或者說最上層的記錄器就是root logger。如果name=None,構建的是root logger。
可以直接用當前模塊的名稱當作記錄器的名字logging.getLogger(__name__)
子級記錄器通常不需要多帶帶設置日志級別以及Handler,如果子級記錄器沒有多帶帶設置,則它的行為會委托給父級。比如說,記錄器foo的級別為INFO,而foo.a和foo.b都不設置日志級別。此時foo.a和foo.b會遵循foo的級別設置,即只記錄大于等于INFO級別的日志;而如果foo也沒設置的話,就會找到根記錄器root logger,root默認的級別為WARGING。
logger類的一些常用的方法
logger結合后面要介紹的其他的三個組件可以實現以下的功能:
Logger需要通過handler將日志信息輸出到目標位置,目標位置可以是sys.stdout和文件等(這與logging.basicConfig(**kwargs)設置中不太一致)。
一個Logger可以設置不同的Handler,而不同的Handler可以將日志輸出到不同的位置(不同的日志文件),并且每個Handler都可以設置自己的filter從而實現日志過濾,保留實際項目中需要的日志。同時每個Handler也可以設置不同的Formatter,在每個Formatter實現同一條日志以不同的格式輸出到不同的地方。
Handle
處理器;其可以控制記錄的日志輸出到什么地方(標準輸出/文件/...),同時處理器也可以添加過濾器(filter)和格式控制器(formatter)來控制輸出的內容和輸出的格式。
其具有幾種常見的處理器:
logging.StreamHandler標準流處理器,將消息發送到標準輸出流、錯誤流-->logging.StreamHandler(sys.stdout)#sys.stdout表示的是指向控制臺即標準輸出;當我們在Python中打印對象調用print obj時候,事實上是調用了sys.stdout.write(obj+'\n')。
print將你需要的內容打印到了控制臺,然后追加了一個換行符
logging.FileHandler文件處理器,將消息發送到文件-->logging.FileHandler(log_path)
logging.RotatingFileHandler文件處理器,文件達到指定大小后,啟用新文件存儲日志
logging.TimedRotatingFileHandler文件處理器,日志以特定的時間間隔輪換日志文件
handle類的一些常用的方法
Filter
filter組件用來過濾logger對象,一個filter可以直接添加到logger對象上,也可以添加到handler對象上,而如果在logger和handler中都設置了filter,則日志是先通過logger的filter,再通過handler的filter。由于所有的信息都可以經過filter,所以filter不僅可以過濾信息,還可以增加信息。
Filter類的實例化對象可以通過logging.Filter(name)來創建,其中name為記錄器的名字,如果沒有創建過該名字的記錄器,就不會輸出任何日志:
filter=logging.Filter("foo.a")
基本過濾器類只允許低于指定的日志記錄器層級結構中低于特定層級的事件,例如這個用foo.a初始化的過濾器,則foo.a.b;foo.a.c等日志記錄器記錄的日志都可以通過過濾器,而foo.c;a.foo等就不能通過。如果name為空字符串,則所有的日志都能通過。
Filter類有三個方法:
addFilter(filter):為logger(logger..addFilter(filter))或者handler(handler..addFilter(filter))增加過濾器
removeFilter(filter):為logger或者handler刪除一個過濾器
filter(record):表示是否要記錄指定的記錄?返回零表示否,非零表示是。一般自定義Filter需要繼承Filter基類,并重寫filter方法
Formatter
格式化日志的輸出;實例化:formatter=logging.Formatter(fmt=None,datefmt=None);如果不指明fmt,將默認使用‘%(message)s’,如果不指明datefmt,將默認使用ISO8601日期格式。
其中fmt參數有以下選項:
例如:
formatter=logging.Formatter('%(asctime)s%(levelname)-8s:%(message)s')#-表示右對齊8表示取8位 handler.formatter=formatter
datefmt參數有以下選項:
例如:
formatter=logging.Formatter('%(asctime)s%(levelname)-8s:%(message)s')#-表示右對齊8表示取8位
handler.formatter=formatter
datefmt參數有以下選項:
例子:
formatter=logging.Formatter("%(asctime)s%(levelname)s%(message)s","%Y%m%d-%H:%M:%S") handler.formatter=formatter
logging的配置
conf形式的配置
在loguser.conf中寫入相關的信息
[loggers] keys=root,fileLogger,rotatingFileLogger [handlers] keys=consoleHandler,fileHandler,rotatingFileHandler [formatters] keys=simpleFormatter [logger_root] level=INFO handlers=consoleHandler [logger_fileLogger] level=INFO handlers=fileHandler qualname=fileLogger propagate=0 [logger_rotatingFileLogger] level=INFO handlers=consoleHandler,rotatingFileHandler qualname=rotatingFileLogger propagate=0 [handler_consoleHandler] class=StreamHandler level=INFO formatter=simpleFormatter args=(sys.stdout,) [handler_fileHandler] class=FileHandler level=INFO formatter=simpleFormatter args=("logs/fileHandler_test.log","a") [handler_rotatingFileHandler] class=handlers.RotatingFileHandler level=WARNING formatter=simpleFormatter args=("logs/rotatingFileHandler.log","a",10*1024*1024,50) [formatter_simpleFormatter] format=%(asctime)s-%(module)s-%(levelname)s-%(thread)d:%(message)s datefmt=%Y-%m-%d%H:%M:%S
在使用logger時,直接導入配置文件即可
from logging import config with open('./loguser.conf','r',encoding='utf-8')as f: ##加載配置 config.fileConfig(f) ##創建同名Logger,其按照配置文件的handle,formatter,filter方法初始化 logger=logging.getLogger(name="fileLogger")
yaml形式配置文件
在loguser.yaml文件中配置相關信息 version:1 disable_existing_loggers:False #formatters配置了日志輸出時的樣式 #formatters定義了一組formatID,有不同的格式; formatters: brief: format:"%(asctime)s-%(message)s" simple: format:"%(asctime)s-[%(name)s]-[%(levelname)s]:%(levelno)s:%(message)s" datefmt:'%F%T' #handlers配置了需要處理的日志信息,logging模塊的handler只有streamhandler和filehandler handlers: console: class:logging.StreamHandler formatter:brief level:DEBUG stream:ext://sys.stdout info_file_handler: class:logging.FileHandler formatter:simple level:ERROR filename:./logs/debug_test.log error_file_handler: class:logging.handlers.RotatingFileHandler level:ERROR formatter:simple filename:./logs/errors.log maxBytes:10485760#10MB#1024*1024*10 backupCount:50 encoding:utf8 loggers: #fileLogger,就是在代碼中通過logger=logging.getLogger("fileLogger")來獲得該類型的logger my_testyaml: level:DEBUG handlers:[console,info_file_handler,error_file_handler] #root為默認情況下的輸出配置,當logging.getLogger("fileLoggername")里面的fileLoggername沒有傳值的時候, #就是用的這個默認的root,如logging.getLogger(__name__)或logging.getLogger() root: level:DEBUG handlers:[console]
同樣的可以通過導入yaml文件加載配置
with open('./loguser.yaml','r',encoding='utf-8')as f: yaml_config=yaml.load(stream=f,Loader=yaml.FullLoader) config.dictConfig(config=yaml_config) root=logging.getLogger() #子記錄器的名字與配置文件中loggers字段內的保持一致 #loggers: #my_testyaml: #level:DEBUG #handlers:[console,info_file_handler,error_file_handler] my_testyaml=logging.getLogger("my_testyaml")
logging和print的區別
看起來logging要比print復雜多了,那么為什么推薦在項目中使用logging記錄日志而不是使用print輸出程序信息呢。
相比與print logging具有以下優點:
可以通過設置不同的日志等級,在release版本中只輸出重要信息,而不必顯示大量的調試信息;
print將所有信息都輸出到標準輸出中,嚴重影響開發者從標準輸出中查看其它數據;logging則可以由開發者決定將信息輸出到什么地方,以及怎么輸出;
和print相比,logging是線程安全的。(python 3中print也是線程安全的了,而python 2中的print不是)(線程安全是指在多線程時程序不會運行混亂;而python 2中的print分兩步打印信息,第一打印字符串,第二打印換行符,如果在這中間發生線程切換就會產生輸出混亂。這就是為什么python2的print不是原子操作,也就是說其不是線程安全的)印信息,第一打印字符串,第二打印換行符,如果在這中間發生線程切換就會產生輸出混亂。這就是為什么python2的print不是原子操作,也就是說其不是線程安全的)
綜上所述,具體的詳細內容,小編就給大家介紹完畢了,希望可以給大家帶來幫助。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/127992.html
摘要:每一條日志記錄也包含級別,代表對應消息的嚴重程度。即格式化器,主要功能是確定最終輸出的形式和內容。最好是日志能夠按自然天進行記錄和分割。 上一章學習了自動化測試,很好,現在我們可以絞盡腦汁寫出一份全面的測試,來保證代碼永遠健康了。 話雖如此,但是作為一個獨立開發者很難寫出真正全面的測試代碼。這是因為用戶在使用你的網站時可不會循規蹈矩,而是會以各種怪異的姿勢瀏覽網頁、上傳數據。但這也不是...
Python的三種主要模塊介紹 小編寫這篇文章的主要目的,給大家介紹三種主要的模塊,包括系統內的幾種模塊,對其做個具體的介紹,下面就給大家詳細的解答下。 在python中,一個文件(以.py為后綴名的文件)就叫做一個模塊,每一個模塊在python里都被看做是一個獨立的文件。 模塊可以被項目中的其他模塊、一些腳本甚至是交互式的解析器所使用,它可以被其他程序引用,從而使用該模塊里的函數等功能...
摘要:盡量使用內置的異常處理語句來替換語句,比如語句,方法。以上是最簡單的重新拋出異常的做法,也是推薦的做法。除了包含所有的外還包含了,和三個異常。避免在語句塊中干一些沒意義的事情,捕獲異常也是需要成本的。 異常處理在任何一門編程語言里都是值得關注的一個話題,良好的異常處理可以讓你的程序更加健壯,清晰的錯誤信息更能幫助你快速修復問題。在Python中,和不部分高級語言一樣,使用了try/ex...
摘要:下載器負責獲取頁面,然后將它們交給引擎來處理。內置了一些下載器中間件,這些中間件將在后面介紹。下載器中間件下載器中間件可以在引擎和爬蟲之間操縱請求和響應對象。爬蟲中間件與下載器中間件類似,啟用爬蟲中間件需要一個字典來配置。 前段時間我寫了一篇《scrapy快速入門》,簡單介紹了一點scrapy的知識。最近我的搬瓦工讓墻了,而且我又學了一點mongodb的知識,所以這次就來介紹一些scr...
閱讀 911·2023-01-14 11:38
閱讀 878·2023-01-14 11:04
閱讀 740·2023-01-14 10:48
閱讀 1983·2023-01-14 10:34
閱讀 942·2023-01-14 10:24
閱讀 819·2023-01-14 10:18
閱讀 499·2023-01-14 10:09
閱讀 572·2023-01-14 10:02