天天看點

python logging子產品的作用_python logging子產品詳解

建立Logger執行個體後,可以使用以下方法進行日志級别設定,增加處理器Handler。

logger.setLevel(logging.ERROR) # 設定日志級别為ERROR,即隻有日志級别大于等于ERROR的日志才會輸出

logger.addHandler(handler_name) # 為Logger執行個體增加一個處理器

logger.removeHandler(handler_name) # 為Logger執行個體删除一個處理器

3.2 Handler 處理器

Handler處理器類型有很多種,比較常用的有三個,StreamHandler,FileHandler,NullHandler,詳情可以通路Python logging.handlers

建立StreamHandler之後,可以通過使用以下方法設定日志級别,設定格式化器Formatter,增加或删除過濾器Filter。

ch.setLevel(logging.WARN) # 指定日志級别,低于WARN級别的日志将被忽略

ch.setFormatter(formatter_name) # 設定一個格式化器formatter

ch.addFilter(filter_name) # 增加一個過濾器,可以增加多個

ch.removeFilter(filter_name) # 删除一個過濾器

3.2.1 StreamHandler

建立方法: sh = logging.StreamHandler(stream=None)

3.2.2 FileHandler

建立方法: fh = logging.FileHandler(filename, mode='a', encoding=None, delay=False)

3.2.3 NullHandler

NullHandler類位于核心logging包,不做任何的格式化或者輸出。

本質上它是個“什麼都不做”的handler,由庫開發者使用。

3.2.4 其他Handler介紹

3.2.4.1 handlers.RotatingFileHandler

類似于上面的FileHandler,但是它可以管理檔案大小。當檔案達到一定大小之後,它會自動将目前日志檔案改名,然後建立一個新的同名日志檔案繼續輸出。

3.2.4.2 handlers.TimedRotatingFileHandle

和RotatingFileHandler類似,不過,它沒有通過判斷檔案大小來決定何時重新建立日志檔案,而是間隔一定時間就自動建立新的日志檔案

3.2.4.3 handlers.SocketHandler

使用TCP協定,将日志資訊發送到網絡。

3.2.4.4 handlers.DatagramHandler

使用UDP協定,将日志資訊發送到網絡。

3.2.4.5 handlers.SysLogHandler

日志輸出到syslog

3.2.4.6 handlers.NTEventLogHandler

遠端輸出日志到Windows NT/2000/XP的事件日志

3.2.4.7 handlers.SMTPHandler

遠端輸出日志到郵件位址

3.2.4.8 handlers.MemoryHandler

日志輸出到記憶體中的制定buffer

3.2.4.9 handlers.HTTPHandler

通過"GET"或"POST"遠端輸出到HTTP伺服器

3.3 Formatter 格式化器

使用Formatter對象設定日志資訊最後的規則、結構和内容,預設的時間格式為%Y-%m-%d %H:%M:%S。

建立方法: formatter = logging.Formatter(fmt=None, datefmt=None)

其中,fmt是消息的格式化字元串,datefmt是日期字元串。如果不指明fmt,将使用'%(message)s'。如果不指明datefmt,将使用ISO8601日期格式。

代碼示範:

fmt = "%(asctime)-15s %(levelname)s %(filename)s %(lineno)d %(process)d %(message)s"

date_format_str = "%Y-%m-%d %H:%M:%S"

formatter = logging.Formatter(fmt, datefmt)

fmt請參考下文中的4.2.2

datefmt請參考下文中的4.2.3

3.4 Filter 過濾器

Handlers和Loggers可以使用Filters來完成比級别更複雜的過濾。Filter基類隻允許特定Logger層次以下的事件。例如用‘A.B’初始化的Filter允許Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’等記錄的事件,logger‘A.BB’, ‘B.A.B’ 等就不行。 如果用空字元串來初始化,所有的事件都接受。

建立方法: filter = logging.Filter(name='')

以下是相關概念總結:

熟悉了這些概念之後,有另外一個比較重要的事情必須清楚,即Logger是一個樹形層級結構;

Logger可以包含一個或多個Handler和Filter,即Logger與Handler或Fitler是一對多的關系;

一個Logger執行個體可以新增多個Handler,一個Handler可以新增多個格式化器或多個過濾器,而且日志級别将會繼承。

python logging子產品的作用_python logging子產品詳解

四、Logging工作流程

第一次導入logging子產品或使用reload函數重新導入logging子產品,logging子產品中的代碼将被執行,這個過程中将産生logging日志系統的預設配置。

自定義配置(可選)。logging标準子產品支援三種配置方式: dictConfig,fileConfig,listen。其中,dictConfig是通過一個字典進行配置Logger,Handler,Filter,Formatter;fileConfig則是通過一個檔案進行配置;而listen則監聽一個網絡端口,通過接收網絡資料來進行配置。當然,除了以上集體化配置外,也可以直接調用Logger,Handler等對象中的方法在代碼中來顯式配置。

使用logging子產品的全局作用域中的getLogger函數來得到一個Logger對象執行個體(其參數即是一個字元串,表示Logger對象執行個體的名字,即通過該名字來得到相應的Logger對象執行個體)。

使用Logger對象中的debug,info,error,warn,critical等方法記錄日志資訊。

4.1 logging子產品處理流程

python logging子產品的作用_python logging子產品詳解

判斷日志的等級是否大于Logger對象的等級,如果大于,則往下執行,否則,流程結束。

産生日志。第一步,判斷是否有異常,如果有,則添加異常資訊。第二步,處理日志記錄方法(如debug,info等)中的占位符,即一般的字元串格式化處理。

使用注冊到Logger對象中的Filters進行過濾。如果有多個過濾器,則依次過濾;隻要有一個過濾器傳回假,則過濾結束,且該日志資訊将丢棄,不再處理,而處理流程也至此結束。否則,處理流程往下執行。

在目前Logger對象中查找Handlers,如果找不到任何Handler,則往上到該Logger對象的父Logger中查找;如果找到一個或多個Handler,則依次用Handler來處理日志資訊。但在每個Handler處理日志資訊過程中,會首先判斷日志資訊的等級是否大于該Handler的等級,如果大于,則往下執行(由Logger對象進入Handler對象中),否則,處理流程結束。

執行Handler對象中的filter方法,該方法會依次執行注冊到該Handler對象中的Filter。如果有一個Filter判斷該日志資訊為假,則此後的所有Filter都不再執行,而直接将該日志資訊丢棄,處理流程結束。

使用Formatter類格式化最終的輸出結果。 注:Formatter同上述第2步的字元串格式化不同,它會添加額外的資訊,比如日志産生的時間,産生日志的源代碼所在的源檔案的路徑等等。

真正地輸出日志資訊(到網絡,檔案,終端,郵件等)。至于輸出到哪個目的地,由Handler的種類來決定。

5 配置擷取方式

顯式建立記錄器Logger、處理器Handler和格式化器Formatter,并進行相關設定;

通過簡單方式進行配置,使用basicConfig()函數直接進行配置;

通過配置檔案進行配置,使用fileConfig()函數讀取配置檔案;

通過配置字典進行配置,使用dictConfig()函數讀取配置資訊;

通過網絡進行配置,使用listen()函數進行網絡配置。

5.1 basicConfig關鍵字參數

關鍵字

描述

filename

建立一個FileHandler,使用指定的檔案名,而不是使用StreamHandler

filemode

如果指明了檔案名,指明打開檔案的模式(如果沒有指明filemode,預設為'a')

format

handler使用指明的格式化字元串

datefmt

使用指明的日期/時間格式

level

指明根logger的級别

stream

使用指明的流來初始化StreamHandler。該參數與'filename'不相容,如果兩個都有,'stream'被忽略

5.1.1 有用的format格式

格式

描述

%(levelno)s

列印日志級别的數值

%(levelname)s

列印日志級别名稱

%(pathname)s

列印目前執行程式的路徑

%(filename)s

列印目前執行程式名稱

%(funcName)s

列印日志的目前函數

%(lineno)d

列印日志的目前行号

%(asctime)s

列印日志的時間

%(thread)d

列印線程id

%(threadName)s

列印線程名稱

%(process)d

列印程序ID

%(message)s

列印日志資訊

5.1.2 有用的datefmt格式

格式

描述

%y

兩位數的年份表示(00-99)

%Y

四位數的年份表示(000-9999)

%m

月份(01-12)

%d

月内中的一天(0-31)

%H

24小時制小時數(0-23)

%I

12小時制小時數(01-12)

%M

分鐘數(00=59)

%S

秒(00-59)

%a

本地簡化星期名稱

%A

本地完整星期名稱

%b

本地簡化的月份名稱

%B

本地完整的月份名稱

%c

本地相應的日期表示和時間表示

%j

年内的一天(001-366)

%p

本地A.M.或P.M.的等價符

%U

一年中的星期數(00-53)星期天為星期的開始

%w

星期(0-6),星期天為星期的開始

%W

一年中的星期數(00-53)星期一為星期的開始

%x

本地相應的日期表示

%X

本地相應的時間表示

%Z

目前時區的名稱

%%

%号本身

五、代碼示例

5.1 示例1

# -*- coding: utf-8 -*-

# @File : log.py

# Create Time: 12/24/2019 10:16 AM

# Usage, put your example for your API

#

#

# Create by : JunPing Ge

# changelog:

#

import logging

logger_name = 'example'

logger = logging.getLogger(logger_name)

logger.setLevel(logging.DEBUG)

log_path = './log.log'

file_handler = logging.FileHandler(log_path)

file_handler.setLevel(logging.WARNING)

stream_handler = logging.StreamHandler()

stream_handler.setLevel(logging.DEBUG)

format_str = "%(asctime)-15s %(levelname)s %(filename)s %(lineno)d %(message)s"

date_format_str = "%Y-%m-%d %H:%M:%S"

formatter = logging.Formatter(format_str,date_format_str)

file_handler.setFormatter(formatter)

stream_handler.setFormatter(formatter)

logger.addHandler(file_handler)

logger.addHandler(stream_handler)

logger.info('info message')

logger.debug('debug message')

logger.warning('warn message')

logger.error('error message')

logger.critical('critical message')

cmd列印資訊如下:

2019-12-24 14:22:54 INFO log.py 31 info message

2019-12-24 14:22:54 DEBUG log.py 32 debug message

2019-12-24 14:22:54 WARNING log.py 33 warn message

2019-12-24 14:22:54 ERROR log.py 34 error message

2019-12-24 14:22:54 CRITICAL log.py 35 critical message

log.log檔案列印資訊如下:

2019-12-24 14:22:54 WARNING log.py 33 warn message

2019-12-24 14:22:54 ERROR log.py 34 error message

2019-12-24 14:22:54 CRITICAL log.py 35 critical message

5.2 從檔案中讀取配置資訊

logging.conf代碼如下:

[loggers]

keys=root,simpleExample

[handlers]

keys=consoleHandler

[formatters]

keys=simpleFormatter

[logger_root]

level=DEBUG

handlers=consoleHandler

[logger_simpleExample]

level=DEBUG

handlers=consoleHandler

qualname=simpleExample

propagate=0

[handler_consoleHandler]

class=StreamHandler

level=DEBUG

formatter=simpleFormatter

args=(sys.stdout,)

[formatter_simpleFormatter]

format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

datefmt=

主程式代碼如下:

# -*- coding: utf-8 -*-

import logging

import logging.config

logging.config.fileConfig("logging.conf") # 采用配置檔案

# create logger

logger = logging.getLogger("simpleExample")

# "application" code

logger.debug("debug message")

logger.info("info message")

logger.warning("warn message")

logger.error("error message")

logger.critical("critical message")

cmd列印資訊如下:

C:\ProgramData\Miniconda3\python.exe G:/gejunping/extract_bin/Merge_bin/read_logging.py

2019-12-24 14:28:39,524 - simpleExample - DEBUG - debug message

2019-12-24 14:28:39,524 - simpleExample - INFO - info message

2019-12-24 14:28:39,524 - simpleExample - WARNING - warn message

2019-12-24 14:28:39,524 - simpleExample - ERROR - error message

2019-12-24 14:28:39,524 - simpleExample - CRITICAL - critical message

5.3 多子產品使用logging

同一個python解釋器内,多次調用logging.getLogger('log_name')都會傳回同一個logger執行個體。