Python日志详解【两篇就够了系列】--第一篇logging
目錄
第一章 Python日志模塊logging詳解
一、logging的框架
1.Logger
2.Handler
3.Formater類
4.Filter類
二、Log級別
三、Log格式
四、常用方式
1.不添加handler用法
2.SysLogHandler
3.RotatingFileHandler
4.TimedRotatingFileHandler
5.自定義Handler,繼承TimedRotatingFileHandler實現壓縮
五、其他說明
1.參考文獻
2.Python其他日志模塊
3. syslog與logging誰更好
4. logging.SysLogHandler和syslog
第一章 Python日志模塊logging詳解
一、logging的框架
logging模塊定義的函數和類為應用程序和庫的開發實現了一個靈活的事件日志系統。logging模塊是Python的一個標準庫模塊,由標準庫模塊提供日志記錄API的關鍵好處是所有Python模塊都可以使用這個日志記錄功能。logging模塊主要包括以下幾個組件。
| 組件 | 說明 |
| loggers | 提供應用程序代碼直接使用的接口 |
| handlers | 用于將日志記錄發送到指定的目的位置 |
| filters | 提供更細粒度的日志過濾功能,用于決定哪些日志記錄將會被輸出。 |
| formatters | 用于控制日志信息的最終輸出格式 |
1.Logger
Logger對象有3個任務要做:
1)向應用程序代碼暴露幾個方法,使應用程序可以在運行時記錄日志消息;
2)基于日志嚴重等級(默認的過濾設施)或filter對象來決定要對哪些日志進行后續處理;
3)將日志消息傳送給所有感興趣的日志handlers。
Logger對象最常用的配置方法如下:
| 方法 | 描述 |
| Logger.setLevel() | 設置日志器將會處理的日志消息的最低嚴重級別 |
| Logger.addHandler() | 為該logger對象添加一個handler對象 |
| Logger.addFilter() | 為該logger對象添加一個filter對象 |
2.Handler
Handler對象的作用是(基于日志消息的level)將消息分發到handler指定的位置(文件、網絡、郵件等)。Logger對象可以通過addHandler()方法為自己添加0個或者多個handler對象。比如,一個應用程序可能想要實現以下幾個日志需求:
1)把所有日志都發送到一個日志文件中;
2)把所有嚴重級別大于等于error的日志發送到stdout(標準輸出);
3)把所有嚴重級別為critical的日志發送到一個email郵件地址。
這種場景就需要3個不同的handlers,每個handler復雜發送一個特定嚴重級別的日志到一個特定的位置。
一個handler中只有非常少數的方法是需要應用開發人員去關心的。對于使用內建handler對象的應用開發人員來說,似乎唯一相關的handler方法就是下面這幾個配置方法:
| 方法 | 描述 |
| Handler.setLevel() | 設置handler將會處理的日志消息的最低嚴重級別 |
| Handler.setFormatter() | 為handler設置一個格式器對象 |
| Handler.addFilter() | 為handler添加一個過濾器對象 |
需要說明的是,應用程序代碼不應該直接實例化和使用Handler實例。因為Handler是一個基類,它只定義了素有handlers都應該有的接口,同時提供了一些子類可以直接使用或覆蓋的默認行為。下面是python提供的全部handler。
?
| Handler | 說明 |
| StreamHandler | 實例將消息發送到流(類似文件的對象) |
| FileHandler | 實例將消息發送到磁盤文件 |
| BaseRotatingHandler | 是RotatingFileHandler和TimedRotatingFileHandler的基類 |
| RotatingFileHandler | 實例將消息發送到磁盤文件,支持日志按大小切割 |
| TimedRotatingFileHandler | 實例將消息發送到磁盤文件,支持按時間切割 |
| SocketHandler | 實例將消息發送到TCP / IP套接字。 |
| DatagramHandler | 實例將消息發送到UDP套接字。 |
| SMTPHandler | 實例將消息發送到指定的電子郵件地址 |
| SysLogHandler | 實例將消息發送到Unix syslog守護程序(可能在遠程計算機上) |
| NTEventLogHandler | 實例將消息發送到Windows NT / 2000 / XP事件日志。 |
| MemoryHandler | 實例將消息發送到內存中的緩沖區,只要滿足特定條件,該緩沖區就會被刷新。 |
| HTTPHandler | 實例使用GET或POST語義將消息發送到HTTP服務器。 |
| WatchedFileHandler | 實例監視他們正在登錄的文件。如果文件更改,則使用文件名將其關閉并重新打開。該處理程序僅在類似Unix的系統上有用。Windows不支持所使用的基礎機制。 |
| QueueHandler | 實例將消息發送到隊列,例如在queue或multiprocessing模塊中實現的消息。 |
| NullHandler | 實例不處理錯誤消息。希望使用日志記錄但希望避免出現“找不到用于記錄器XXX的處理程序”消息的庫開發人員會使用它們,如果庫用戶未配置日志記錄,則會顯示該消息。有關更多信息,請參見為庫配置日志。 |
3.Formater類
Formater對象用于配置日志信息的最終順序、結構和內容。與logging.Handler基類不同的是,應用代碼可以直接實例化Formatter類。
4.Filter類
Filter可以被Handler和Logger用來做比level更細粒度的、更復雜的過濾功能。Filter是一個過濾器基類,它只允許某個logger層級下的日志事件通過過濾。日志事件信息流如圖所示。
二、Log級別
系統默認有6個級別,優先級:
| 級別 | 數值 | 使用時 |
| CRITICAL??? | 50 | 嚴重錯誤,表明程序本身可能無法繼續運行。 |
| ERROR | 40 | 由于存在更嚴重的問題,該軟件無法執行某些功能。 |
| WARNING | 30 | 表示發生了意外情況,或者表示在不久的將來出現了某些問題(例如“磁盤空間不足”)。該軟件仍按預期運行。 |
| INFO | 20 | 確認一切正常。 |
| DEBUG | 10 | 詳細信息,通常僅在診斷問題時才需要。 |
| NOTSET | 0 | ? |
設置要打印的log時只需要設置優先級,比如設置打印INFO,那么比INFO優先級高的WARNING/ERROR/CRITICAL都將被打印,默認級別為WARNING。
三、Log格式
?
| %(name)s | Logger的名字 |
| %(levelno)s | 數字形式的日志級別 |
| %(levelname)s | 文本形式的日志級別 |
| %(pathname)s | 調用日志輸出函數的模塊的完整路徑名,可能沒有 |
| %(filename)s | 調用日志輸出函數的模塊的文件名 |
| %(module)s | 調用日志輸出函數的模塊名 |
| %(funcName)s | 調用日志輸出函數的函數名 |
| %(lineno)d | 調用日志輸出函數的語句所在的代碼行 |
| %(created)f | 當前時間,用UNIX標準的表示時間的浮點數表示 |
| %(relativeCreated)d | 輸出日志信息時的,自Logger創建以來的毫秒數 |
| %(asctime)s | 字符串形式的當前時間。默認格式是 “2003-07-08 16:49:45,896”。逗號后面的是毫秒 |
| %(thread)d | 線程ID(可能沒有) |
| %(threadName)s | 線程名(可能沒有) |
| %(process)d | 進程ID(可能沒有) |
| %(message)s | 用戶輸出的消息 |
?
四、常用方式
1.不添加handler用法
import loggingLOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"logging.basicConfig(filename='my.log', level=logging.DEBUG, format=LOG_FORMAT, datefmt=DATE_FORMAT)logging.debug("This is a debug log.")logging.info("This is a info log.")logging.warning("This is a warning log.")logging.error("This is a error log.")logging.critical("This is a critical log.")打印日志結果
| 11/26/2020 04:14:38 AM - DEBUG - This is a debug log. 11/26/2020 04:14:38 AM - INFO - This is a info log. 11/26/2020 04:14:38 AM - WARNING - This is a warning log. 11/26/2020 04:14:38 AM - ERROR - This is a error log. 11/26/2020 04:14:38 AM - CRITICAL - This is a critical log. |
2.SysLogHandler
SysLogHandler是logging中的一個handler,是把日志輸入的系統日志。
使用方法
import loggingfrom logging.handlers import SysLogHandlerlogger = logging.getLogger("kyc")logger.setLevel(logging.DEBUG)handler = SysLogHandler(address='/dev/log')logger.addHandler(handler)log = logging.getLogger("kyc")log.info("kangyucheng test SysLogHandler")運行程序,可以發現。
在/var/log/messages中打印一條消息
當然,這個也可把日志配置到其他的位置。
3.RotatingFileHandler
RotatingFileHandler可以實現將日志按大小切割,當日志文件達到預設大小后,會將這個日志拷貝到一個新的文件當中。實現如下。
# -*- encoding= utf-8 -*-import loggingfrom logging.handlers import RotatingFileHandler"""log_file_name是日志路徑file_size是文件切割大小log_level是日志級別backup_count是文件數量formatter是日志的格式"""rotating_log_conf = {"yuhceng": {"log_file_name": "/var/log/yucheng/yucheng.log","file_size": 5000,"log_level": logging.DEBUG,"backup_count": 10,"formatter": "yuhcheng:[%(levelname)s] %(pathname)s line-%(lineno)d:%(message)s"}}def config_log():for name, conf in rotating_log_conf.items():logger = logging.getLogger(name)log_level = conf.get("log_level", logging.INFO)logger.setLevel(log_level)rotating_handler = RotatingFileHandler(filename=conf.get("log_file_name"),maxBytes=conf.get("file_size", 0),backupCount=conf.get("backup_count", 0))rotating_handler.setFormatter(logging.Formatter(conf.get("formatter")))logger.addHandler(rotating_handler)if __name__ == '__main__':config_log()log = logging.getLogger("yucheng")for i in range(1000000000000):log.info("yucheng".format(str(i)))結果如下。
4.TimedRotatingFileHandler
import loggingimport timefrom logging.handlers import TimedRotatingFileHandlerlogHandler = TimedRotatingFileHandler(filename="log/yucheng.log", when="S", interval=5,backupCount=3, encoding='utf-8')logHandler.suffix = "%Y%m%d%H%M"logFormatter = logging.Formatter('[%(asctime)s %(filename)s:%(lineno)d %(levelname)s] %(message)s')logHandler.setFormatter(logFormatter)logger = logging.getLogger('MyLogger')logger.addHandler(logHandler)logger.setLevel(logging.INFO)for k in range(30000000):logger.error("eror info: %d" % k)time.sleep(0.1)log文件夾下面,每分鐘會對日志進行切割,隨時間變化。
5.自定義Handler,繼承TimedRotatingFileHandler實現壓縮
?
雖然TimedRotatingFileHandler可以實現按照時間切割,但是不能對日志文件壓縮。可以通過繼承TimedRotatingFileHandler,覆蓋其doRollover方法,在該方法中實現壓縮日志文件和刪除舊日志文件。日志文件按照預期,壓縮。
?
?
分別查看兩個壓縮后的日志內容,日志沒有缺失。
實驗結果表明,這種日志壓縮的方式可行。
在查看日志的時候,不能夠直接用vim 或vi或tail或cat查看,
需要使用zcat。
例如,把文件內容重定向到文件中
| zcat test.log.2021-01-01_16-03-20.gz >>2.txt |
以上方法的有點在于,對于日志壓縮確實能夠實現日志空間減少。
但也引入了風險,壓縮方法需要自行實現,若自行實現引入bug反而得不償失。
?
五、其他說明
1.參考文獻
https://docs.python.org/3/howto/logging.html
2.Python其他日志模塊
syslog模塊為提供了rsyslog模塊的一個接口。可以記錄程序運行時的輸出信息。
使用方法
| import syslog syslog.syslog("kangyucheng") |
運行程序,可以發現。
在/var/log/messages中打印一條消息
3. syslog與logging誰更好
(1)syslog只是對rsyslog的一個調用,依賴于系統rsyslog,而在實際的使用過程中rsyslog并不穩定。在系統運行過程中,日志多次報錯。從這一點考慮要使用logging更好。
(2)當然上文說rsyslog并不穩定,也可能是在使用過程中配置有誤。除此之外,仍有其他理由。軟件的設計要高內聚低耦合,日志模塊本屬于軟件程序本身,倘若將日志壓縮等任務交給系統來做,顯然不符合軟件設計的理念。除此之外,每次部署都要去修改日志配置,這無疑增加了部署難度。
4. logging.SysLogHandler和syslog
SysLogHandler是logging中的一個handler。syslog是另外一個包,兩個都可以將日志寫入系統日志。
?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Python日志详解【两篇就够了系列】--第一篇logging的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分布式存储的集群可靠性计算(ceph)
- 下一篇: Python日志详解【两篇就够了系列】-