@(雜庭憶技)[Python, logging]css
018.8.17html
import logging
logging.debug("debug")
logging.info("info")
logging.warning("warning")
logging.error("error")
# 輸出
>>WARNING:root:warning
>>ERROR:root:error
默認狀況下,logging將日誌打印到屏幕上,按WARNING級別python
CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET服務器
設置日誌等級之後,程序會自動過濾掉低於設置等級的日誌信息。如:當等級爲WARNING的時候,包括INFO及如下的日誌信息會被過濾掉socket
利用logging模塊中的basicConfig()
方法對日誌作簡單設置函數
import logging
# 設置日誌的基本信息
logging.basicConfig(
level=logging.DEBUG, # 設置等級
filename = "test.log", # 設置輸出文件
datefmt = "%Y/%m/%d %H:%M:%S", # 設置時間格式
format = "【%(asctime)s %(levelname)s】 %(lineno)d: %(message)s") # 設置輸出格式
logging.debug("debug")
logging.info("info")
logging.warning("warning")
logging.error("error")
運行程序以後,當前目錄下會生成一個test.log的文件,內容以下:
spa
可見輸出格式是按照參數format指定樣子生成的,而asctime,levelname,lineno指定的是須要輸出哪些內容,這裏依次是:時間,日誌等級,出現行號,以及日誌內容;若是不看小括號中的內容,其實%s,%d就是格式佔位符線程
固然basicConfig()
的用法並無完,完整參數以下
- filename:輸出文件路徑
- filemode:按什麼方式寫入,w
表示清空內容以後寫入,a
表示追加(默認追加模式)
- datefmt:設置時間格式
- style:當format傳入了參數的時候,用style參數來指定佔位符,能夠是:%,{,$debug
import logging
# 不指定style時,默認%
logging.basicConfig(
level=logging.DEBUG,
datefmt = "%Y/%m/%d",
filename = "test.log",
format = "%(asctime)s %(message)s")
# 指定用符號 {
logging.basicConfig(
level=logging.DEBUG,
style = "{",
datefmt = "%Y/%m/%d",
filename = "test.log",
format = "{asctime} {message}")
# 指定用符號 $
logging.basicConfig(
level=logging.DEBUG,
style = "{",
datefmt = "%Y/%m/%d",
filename = "test.log",
format = "$asctime $message")
logging.debug("debug")
須要區分%、{、$佔位時的不一樣用法
- level:指定日誌輸出等級,只有大於等於這個等級的日誌纔會被輸出
- stream:輸出流,能夠理解爲輸出到終端,當沒有設置filename參數的時候,默認用StreamHandler;若是同時設置了stream和filename參數,stream的效果將被忽略
- handlers:指定日誌處理時使用的Handler
- format:指定日誌輸出格式。經常使用參數以下:
1. asctime
:時間,默認按照2003-07-08 16:49:45,896格式
2. created
:也是時間,但以時間戳形式輸出
3. filename
:當前執行文件的名字
4. funcName
:當前執行函數的名字
5. levelname
:日誌級別的名稱(WARNING、ERROR…)
6. lineno
:當前行號
7. message
:日誌內容
8. module
:模塊名
9. process
:進程號
10. processName
:進程名字
11. thread
:線程號
12. threadName
:線程名字
13. (更多相關參數可查看官方文檔)3d
前面都是利用logging的basicConfig()
方法配置全局信息,咱們也能夠經過getLogger()
方法返回一個logging.Logger類型的對象進行動態配置
import logging
# 實例一個logger對象,並對其添加文件名
logger = logging.getLogger(__name__)
# 設置日誌級別
logger.setLevel(logging.WARNING)
# 構建日誌格式
formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s")
# 構建一個handler對象,並設置日誌存放路徑
handler = logging.FileHandler("test.log")
# 添加格式
handler.setFormatter(formatter)
# 添加handler
logger.addHandler(handler)
# 輸出日誌
logger.error("error")
咱們也能夠構建多個handler來處理問題,好比將日誌輸出到文件的同時,也在終端輸出
import logging
logger = logging.getLogger(__name__)
formatter = logging.Formatter("【%(asctime)s %(levelname)s】 %(message)s")
# 構建一個StreamHandler,用於輸出到終端
strHandler = logging.StreamHandler()
strHandler.setLevel(logging.WARN) # 設置等級高於WARN以及WARN以上的(WARNING的簡寫)
strHandler.setFormatter(formatter)
logger.addHandler(strHandler)
# 構建一個FileHandler,用於輸出到文件
fileHandler = logging.FileHandler("a-simmple.log")
fileHandler.setLevel(logging.INFO)# 設置等級高於INFO以及INFO以上的(WARNING的簡寫)
fileHandler.setFormatter(formatter)
logger.addHandler(fileHandler)
logger.debug("debug")
logger.info("info")
logger.warning("warning")
logger.error("error")
終端輸出結果以下:
日誌文件內容以下:
須要注意一點,在使用Handler(FileHandler,StreamHandler)對象的setLevel()方法的時候,若是須要設置的日誌級別低於WARNING,則必須對logger對象使用setLevel(),根據具體狀況選擇logging.DEBUG或logging.INFO參數;固然也可使用logging.basicConfig()方法配置全局信息,也能起到一樣的效果,以下:
import logging
logging.basicConfig(level = logging.DEBUG)
logger = logging.getLogger(__name__)
formatter = logging.Formatter("【%(asctime)s %(levelname)s】 %(message)s")
# 構建一個StreamHandler,用於輸出到終端
...(省略)
除FileHandler,StreamHandler外,logging模塊還提供了其餘的Handler(如下都包含在logging.handlers模塊中)
- BaseRotatingHandler:基本的日誌回滾方式
- RotatingHandler:日誌回滾方式,支持日誌文件最大數量和日誌文件回滾
- TimeRotatingHandler:日誌回滾方式,在必定時間區域內回滾日誌文件
- SocketHandler:遠程輸出日誌到TCP/IP sockets
- DatagramHandler:遠程輸出日誌到UDP sockets
- SMTPHandler:遠程輸出日誌到郵件地址
- SysLogHandler:日誌輸出到syslog
- NTEventLogHandler:遠程輸出日誌到Windows NT/2000/XP的事件日誌
- MemoryHandler:日誌輸出到內存中的指定buffer
- HTTPHandler:經過GET或POST遠程輸出到HTTP服務器
利用logging模塊,也能夠詳細記錄Traceback,方便咱們查找問題
import logging
logger = logging.getLogger(__name__)
formatter = logging.Formatter(
"【%(asctime)s %(levelname)s】 %(message)s")
handler = logging.FileHandler("traceback.log")
handler.setFormatter(formatter)
logger.addHandler(handler)
try:
print(name)
except:
logger.error("error", exc_info=True)
運行結果以下:
能夠經過配置父模塊的方法,讓子模塊也受益
""" 父模塊:mainLog.py """
import logging
import dupLog
logger = logging.getLogger("father") # 生成一個logger,併爲其命名「father」
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler("my-log.txt")
formatter = logging.Formatter(
"【%(asctime)s %(levelname)s】 %(name)s: %(message)s ")
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.debug("debug")
logger.info("info")
logger.warning("warning")
dupLog.record_log() # 調用子模塊的日誌記錄功能
""" 子模塊:dupLog.py """
import logging
logger = logging.getLogger("father.son") # 生成一個logger,併爲其命名「father.son」
# 記錄日誌函數
def record_log():
logger.info("info")
logger.error("error")
輸出結果:
"""
日誌文件:my-log.txt
"""
【2018-08-18 07:47:21,775 DEBUG】 father: debug
【2018-08-18 07:47:21,776 INFO】 father: info
【2018-08-18 07:47:21,776 WARNING】 father: warning
【2018-08-18 07:47:21,776 INFO】 father.son: info
【2018-08-18 07:47:21,776 ERROR】 father.son: error
這裏須要注意的是,子模塊的logger名稱必須以父模塊的logger名稱開頭,如上所示的父father,子father.son
儘管設置配置信息的時候有logging.basciConfig()
,logging.getLogger().setLevel()
,logging.Formatter().setFormatter()
等方法,但語句始終鑲嵌在代碼裏,不利於修改,也不利於閱讀。所以logging模塊提供了以加載配置文件的方式對日誌功能進行配置
配置文件: log.conf
[loggers]
keys=root,log02
[handlers]
keys=hand01,hand02
[formatters]
keys=form01,form02
#################################################
[logger_root]
level=NOTSET
handlers=hand01
[logger_log02]
level=WARNING
handlers=hand02
propagate=1
qualname=log02
#################################################
[handler_hand01]
class=FileHandler
level=NOTSET
formatter=form01
args=("mine.log", "w")
[handler_hand02]
class=StreamHandler
level=WARNING
formatter=form02
args=(sys.stdout,)
#################################################
[formatter_form01]
format=[%(asctime)s %(levelname)s]-%(name)s-: %(message)s
datefmt=%Y/%m/%d %H:%M:%S
class=logging.Formatter
[formatter_form02]
format=%(asctime)s %(levelname)s: %(message)s
class=logging.Formatter
執行文件:test_log.py
import logging
import logging.config
logging.config.fileConfig("log.conf") # 加載配置文件
loggerRoot = logging.getLogger("root") # 獲取root的配置
loggerLog02 = logging.getLogger("log02") # 獲取log2的配置
loggerRoot.debug("debug")
loggerRoot.info("info")
loggerRoot.warning("warning")
loggerRoot.error("error")
loggerLog02.warning("warning")
loggerLog02.error("error")
運行結果以下:
- 終端
- mine.log
須要注意如下幾點:
- 配置文件中,必須含有[loggers]
[handlers]
[formatters]
字段
- [loggers]
的keys中,必須含有root,並對其配置
- root會執行全部logger應該執行的debug(),info()...
等方法(因此上示mine.log文件中,有log02的日誌信息)
- 更多詳情可查看官方logging.config信息
文件配置還有另外一種方法,利用logging.config.dictConfig()
方法加載配置信息,配置文件格式以下:
具體使用方法可參看官方文檔說明,也能夠看崔慶才的一篇關於使用logging的文章