在之前的多個項目中都有用到過logging模塊,雖然用過,但沒有研究過,只是在每個代碼文件中使用logger=logging.getLogger(__name__)
這樣簡單粗暴的方法。
在這次的使用經(jīng)歷中,覺得logging模塊真的很不錯。
logging
使用logging前,必須先要了解它的重要概念。
- Logging Levels
- Logger Objects
- Handler Objects
- Formatter Objects
- Filter Objects
Level
Level 級別。只有在日志消息的級別大于logger和handler設(shè)定的級別,才會顯示。
級別 | 何時使用 | |
---|---|---|
NOTSET | 不設(shè)置級別 | 0 |
DEBUG | 詳細(xì)信息,調(diào)試時 | 10 |
INFO | 證明事情按預(yù)期工作。 | 20 |
WARNING | 表明發(fā)生了一些意外,或者不久的將來會發(fā)生問題(如‘磁盤滿了’)。軟件還是在正常工作。 | 30 |
ERROR | 由于更嚴(yán)重的問題,軟件已不能執(zhí)行一些功能了。 | 40 |
CRITICAL | 嚴(yán)重錯誤,表明軟件已不能繼續(xù)運(yùn)行了。 | 50 |
Logger
Logger 記錄器,暴露了應(yīng)用程序代碼能直接使用的接口。
Logger是一個樹形層級結(jié)構(gòu),在使用接口debug,info,warn,error,critical之前必須創(chuàng)建Logger實例,即創(chuàng)建一個記錄器,如果沒有顯式的進(jìn)行創(chuàng)建,則默認(rèn)創(chuàng)建一個root logger,并應(yīng)用默認(rèn)的日志級別(WARN),處理器Handler(StreamHandler,即將日志信息打印輸出在標(biāo)準(zhǔn)輸出上),和格式化器Formatter(默認(rèn)的格式即為第一個簡單使用程序中輸出的格式)。
創(chuàng)建方法: logger = logging.getLogger(name=None)
。如果不指定name則返回root logger對象。
常用方法如下:
方法 | 說明 |
---|---|
addHandler(self, hdlr) | Add the specified handler to this logger. |
removeHandler(self, hdlr) | Remove the specified handler from this logger. |
setLevel(self, level) | Set the logging level of this logger. |
Handler
Handler 處理器,將(記錄器產(chǎn)生的)日志記錄發(fā)送至合適的目的地。
比較常用的有三個,StreamHandler,F(xiàn)ileHandler,NullHandler,詳情可以訪問地址
Handler處理器類型如下:
- StreamHandler
- FileHandler
- NullHandler
- WatchedFileHandler
- RotatingFileHandler
- TimedRotatingFileHandler
- SocketHandler
- DatagramHandler
- SysLogHandler
- NTEventLogHandler
- SMTPHandler
- MemoryHandler
- HTTPHandler
Filter
過濾器,提供了更好的粒度控制,它可以決定輸出哪些日志記錄。
使用Formatter對象設(shè)置日志信息最后的規(guī)則、結(jié)構(gòu)和內(nèi)容,默認(rèn)的時間格式為%Y-%m-%d %H:%M:%S。
創(chuàng)建方法: formatter = logging.Formatter(fmt=None, datefmt=None)
其中,fmt是消息的格式化字符串,datefmt是日期字符串。如果不指明fmt,將使用'%(message)s'。如果不指明datefmt,將使用ISO8601日期格式。
Formatter
格式化器,指明了最終輸出中日志記錄的布局。
Handlers和Loggers可以使用Filters來完成比級別更復(fù)雜的過濾。Filter基類只允許特定Logger層次以下的事件。例如用‘A.B’初始化的Filter允許Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’等記錄的事件,logger‘A.BB’, ‘B.A.B’ 等就不行。 如果用空字符串來初始化,所有的事件都接受。
格式 | 描述 |
---|---|
%(levelno)s | 打印日志級別的數(shù)值 |
%(levelname)s | 打印日志級別名稱 |
%(pathname)s | 打印當(dāng)前執(zhí)行程序的路徑 |
%(filename)s | 打印當(dāng)前執(zhí)行程序名稱 |
%(funcName)s | 打印日志的當(dāng)前函數(shù) |
%(lineno)d | 打印日志的當(dāng)前行號 |
%(asctime)s | 打印日志的時間 |
%(thread)d | 打印線程id |
%(threadName)s | 打印線程名稱 |
%(process)d | 打印進(jìn)程ID |
%(message)s | 打印日志信息 |
使用過程
在項目啟動中導(dǎo)入logging模塊,然后進(jìn)行配置,logging標(biāo)準(zhǔn)模塊支持三種配置方式: dictConfig,fileConfig,listen。其中,dictConfig是通過一個字典進(jìn)行配置Logger,Handler,F(xiàn)ilter,F(xiàn)ormatter;fileConfig則是通過一個文件進(jìn)行配置;而listen則監(jiān)聽一個網(wǎng)絡(luò)端口,通過接收網(wǎng)絡(luò)數(shù)據(jù)來進(jìn)行配置。當(dāng)然,除了以上集體化配置外,也可以直接調(diào)用Logger,Handler等對象中的方法在代碼中來顯式配置。
basicConfig關(guān)鍵字參數(shù)
關(guān)鍵字 | 描述 |
---|---|
filename | 創(chuàng)建一個FileHandler,使用指定的文件名,而不是使用StreamHandler。 |
filemode | 如果指明了文件名,指明打開文件的模式(如果沒有指明filemode,默認(rèn)為'a')。 |
format | handler使用指明的格式化字符串。 |
datefmt | 使用指明的日期/時間格式。 |
level | 指明根logger的級別。 |
stream | 使用指明的流來初始化StreamHandler。該參數(shù)與'filename'不兼容,如果兩個都有,'stream'被忽略。 |
例子:
logging.yaml
logging:
version: 1
formatters:
brief:
format: '%(message)s'
default:
format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
datefmt: '%Y-%m-%d %H:%M:%S'
fluent_fmt:
'()': fluent.handler.FluentRecordFormatter
format:
loglevel: '%(levelname)s'
hostname: '%(hostname)s'
where: '%(module)s.%(funcName)s'
stack_trace: '%(exc_text)s'
handlers:
console:
class : logging.StreamHandler
level: DEBUG
formatter: default
stream: ext://sys.stdout
fluent_dev:
class: fluent.handler.FluentHandler
host: 127.0.0.1
port: 24224
tag: test.dev
formatter: fluent_fmt
level: DEBUG
fluent_prod:
class: fluent.handler.FluentHandler
host: 127.0.0.1
port: 24224
tag: test.prod
formatter: fluent_fmt
level: DEBUG
null:
class: logging.NullHandler
loggers:
amqp:
handlers: [null]
propagate: False
conf:
handlers: [null]
propagate: False
dev:
handlers: [console, fluent_dev]
level: DEBUG
propagate: False
prod:
handlers: [console, fluent_prod]
level: DEBUG
propagate: False
'': # root logger
handlers: [console]
level: DEBUG
propagate: False
導(dǎo)入配置方法:
import yaml
import logging
import logging.config
with open('logging.yaml') as fd:
conf = yaml.load(fd)
logging.config.dictConfig(conf['logging'])
獲取logger
logger = logging.getLogger(loggername)