Python logging 記錄日誌

目錄

1.使用Python的 logging 模塊記錄日誌

2. Python log 的日誌級別

3.logging 日誌格式

4.logging 模塊:Logger 、Handler、Filter、Formatter

5.自動分割日誌文件-日誌文件按照時間劃分或者按照大小劃分

6總結與擴展

7 Linux 下的 rsyslog 日誌服務器

8.參考


官方文檔:

[1]https://docs.python.org/2/library/logging.html

0.程序日誌的重要性

程序日誌的重要性不言而喻,定位問題就會用到日誌信息;另外,通過跟蹤日誌,也可以快速瞭解他人寫的代碼的執行情況。

1.使用Python的 logging 模塊記錄日誌

下面給出一個例子,使用 logging 模塊以一定的格式向控制檯和本地日誌文件  輸出 程序執行過程中的日誌信息:

#-*- coding: UTF-8 -*- 
#!/usr/bin/env python

import logging

def MyLogTest():
    logger = logging.getLogger('MyLogTest')
    logger.setLevel(level=logging.INFO)
    
    LogFormat=logging.Formatter('%(asctime)s - %(pathname)s - %(filename)s-%(funcName)s-[line:%(lineno)d] - %(levelname)s: %(message)s')
    
    file_handler = logging.FileHandler('MyLogTest.log')
    file_handler.setLevel(level=logging.INFO)
    file_handler.setFormatter(LogFormat)
      
    stream_handler = logging.StreamHandler()
    stream_handler.setLevel(logging.DEBUG)
    stream_handler.setFormatter(LogFormat)
    
    logger.addHandler(file_handler)
    logger.addHandler(stream_handler)
      
    logger.debug('debug級別,一般用來打印一些調試信息,級別最低')
    logger.info('info級別,一般用來打印一些正常的操作信息')
    logger.warning('waring級別,一般用來打印警告信息')
    logger.error('error級別,一般用來打印一些錯誤信息')
    logger.critical('critical級別,一般用來打印一些致命的錯誤信息,等級最高')
    
if __name__ == '__main__':
    MyLogTest()
    

控制檯輸出:

2019-12-29 21:01:43,566 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:25] - INFO: info級別,一般用來打印一些正常的操作信息
2019-12-29 21:01:43,589 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:26] - WARNING: waring級別,一般用來打印警告信息
2019-12-29 21:01:43,608 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:27] - ERROR: error級別,一般用來打印一些錯誤信息
2019-12-29 21:01:43,623 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:28] - CRITICAL: critical級別,一般用來打印一些致命的錯誤信息,等級最高

MyLogTest.log文件輸出:

2019-12-29 21:03:52,020 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:25] - INFO: info級別,一般用來打印一些正常的操作信息
2019-12-29 21:03:52,043 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:26] - WARNING: waring級別,一般用來打印警告信息
2019-12-29 21:03:52,051 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:27] - ERROR: error級別,一般用來打印一些錯誤信息
2019-12-29 21:03:52,056 - E:\programming_languages\Python\logging\MyLogTest2.py - MyLogTest2.py-MyLogTest-[line:28] - CRITICAL: critical級別,一般用來打印一些致命的錯誤信息,等級最高

如果想知道 logging 模塊所在路徑,Linux 下同樣適用,適合於查看源代碼,繼承(改造)logging 模塊

>>> import logging
>>> logging
<module 'logging' from 'C:\Python27\lib\logging\__init__.pyc'>

2. Python log 的日誌級別

Python 標準庫 logging 用作記錄日誌,默認分爲六種日誌級別(括號爲級別對應的數值):

1)NOTSET(0)

2)DEBUG(10)

3)INFO(20)

4)WARNING(30)

5)ERROR(40)

6)CRITICAL(50)

 

我們自定義日誌級別時注意不要和默認的日誌級別數值相同,logging 執行時輸出大於等於設置的日誌級別的日誌信息,如設置日誌級別是 INFO,則 INFO、WARNING、ERROR、CRITICAL 級別的日誌都會輸出。

 

3.logging 日誌格式

logging.basicConfig(format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
                    level=logging.DEBUG)
2019-07-19 15:54:26,625 - log_test.py[line:11] - DEBUG: debug級別,一般用來打印一些調試信息,級別最低

format 可以指定輸出的內容和格式,其內置的參數如下:

%(name)s:Logger的名字
%(levelno)s:打印日誌級別的數值
%(levelname)s:打印日誌級別的名稱
%(pathname)s:打印當前執行程序的路徑,其實就是sys.argv[0]
%(filename)s:打印當前執行程序名
%(funcName)s:打印日誌的當前函數
%(lineno)d:打印日誌的當前行號
%(asctime)s:打印日誌的時間
%(thread)d:打印線程ID
%(threadName)s:打印線程名稱
%(process)d:打印進程ID
%(message)s:打印日誌信息

 

4.logging 模塊:Logger 、Handler、Filter、Formatter

logging 庫採取了模塊化的設計,提供了許多組件:記錄器、處理器、過濾器和格式化器

  • Logger 暴露了應用程序代碼能直接使用的接口。
  • Handler 將(記錄器產生的)日誌記錄發送至合適的目的地。
  • Filter 提供了更好的粒度控制,它可以決定輸出哪些日誌記錄。
  • Formatter 指明瞭最終輸出中日誌記錄的內容和格式。

簡單地說,其中 logger 是負責記錄日誌消息的,然後我們要把這些日誌消息放到哪裏,交給 Handler 處理,Filter 則幫我們過濾信息(不限於通過級別過濾,意思是還有其他過濾方式),Formatter 就是跟上面的 format 一個意思,用來設置日誌內容和格式。

Logger 負責記錄日誌

Handler 負責日誌的處理(怎麼輸出,輸出到哪裏)

Formatter 控制日誌的輸出格式

Filter 日誌的過濾控制

 

logger = logging.getLogger('test')
logger.setLevel(level=logging.DEBUG)

formatter = logging.Formatter('%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.DEBUG)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
...

我們發現Formatter是給handler設置的,這很好理解,因爲handler是負責把日誌輸出到哪裏,所以是給它設置格式,而不是給logger;那爲什麼level需要設置兩次呢?給logger設置是告訴它要記錄哪些級別的日誌,給handler設是告訴它要輸出哪些級別的日誌,相當於進行了兩次過濾。這樣的好處在於,當我們有多個日誌去向時,比如既保存到文件,又輸出到控制檯,就可以分別給他們設置不同的級別;logger 的級別是先過濾的,所以被 logger 過濾的日誌 handler 也是無法記錄的,這樣就可以只改 logger 的級別而影響所有輸出。兩者結合可以更方便地管理日誌記錄的級別。
 

5.自動分割日誌文件-日誌文件按照時間劃分或者按照大小劃分

有時候我們需要對日誌文件進行分割,以方便我們的管理。python 提供了兩個處理器,方便我們分割文件:

logging.handlers.RotatingFileHandler -> 按照大小自動分割日誌文件,一旦達到指定的大小重新生成文件
logging.handlers.TimedRotatingFileHandler -> 按照時間自動分割日誌文件

如果將日誌保存在一個文件中,那麼時間一長,或者日誌一多,單個日誌文件就會很大,既不利於備份,也不利於查看。我們會想到能不能按照時間或者大小對日誌文件進行劃分呢?答案肯定是可以的,並且還很簡單,logging 考慮到了我們這個需求。logging.handlers 文件中提供了 TimedRotatingFileHandlerRotatingFileHandler 類分別可以實現按時間和大小劃分。打開這個 handles 文件,可以看到還有其他功能的 Handler 類,它們都繼承自基類 BaseRotatingHandler

# TimedRotatingFileHandler 類構造函數
def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
# RotatingFileHandler 類的構造函數
def __init__(self, filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=False)

示例代碼:

1)按照日誌文件的大小進行劃分:

from logging import handlers

# 每隔 1000 Byte 劃分一個日誌文件,備份文件爲 3 個
file_handler = logging.handlers.RotatingFileHandler("test.log", mode="w", maxBytes=1000, backupCount=3, encoding="utf-8")

2)按照日誌的記錄時間進行劃分:

# 每隔 1小時 劃分一個日誌文件,interval 是時間間隔,備份文件爲 10 個
handler2 = logging.handlers.TimedRotatingFileHandler("test.log", when="H", interval=1, backupCount=10)

若改爲when='S',則以秒爲週期進行切割,運行幾次後會生成文件,文件名以時間爲後綴進行區分,其中沒有後綴的爲最新日誌文件。

 

6總結與擴展

Python logging 庫設計的真的非常靈活,如果有特殊的需要還可以在這個基礎的 logging 庫上進行改進,創建新的 Handler 類解決實際開發中的問題。

Python 官網雖然說 logging 庫是線程安全的,但在多進程、多線程、多進程多線程環境中仍然還有值得考慮的問題,比如,如何將日誌按照進程(或線程)劃分爲不同的日誌文件,也即一個進程(或線程)對應一個文件。

 

 

7 Linux 下的 rsyslog 日誌服務器

 

[1]https://blog.csdn.net/paopaohll/article/details/84388313

 

8.參考

[1]https://blog.csdn.net/Runner1st/article/details/96481954

[2]https://cloud.tencent.com/developer/article/1354396

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章