38. 日誌

星光映梦發表於2024-11-27

一、日誌的基本使用

logger.debug(msg, *args, **kwargs)        # 輸出除錯日誌
logger.info(msg, *args, **kwargs)         # 輸出訊息日誌
logger.warning(msg, *args, **kwargs)      # 輸出警告日誌
logger.error(msg, *args, **kwargs)        # 輸出錯誤日誌
logger.critical(msg, *args, **kwargs)     # 輸出嚴重日誌
logging.basicConfig(**kwargs)             # 配置日式輸出資訊

  在 Python 中系統內建的日誌級別有六種:DEBUG、INFO、WARNING(預設值)、ERROR 以及 CRITICAL,系統會輸出到控制檯或者儲存到日誌檔案的日誌資訊一定是等於或者高於當前等級的資訊,例如當 level=logging.WARNING 時,只會輸出或者儲存 WARNING、ERROR 和 CRITICAL 級別的資訊,其他級別的日誌資訊不會顯示或儲存,這也是 level 這個引數控制輸出的意義所在。

日誌級別 數值
logging.CRITICAL 50
logging.ERROR 40
logging.WARNING 30
logging.INFO 20
logging.DEBUG 10
logging.NOTSET 0

  定義山中日誌輸出格式,日誌中可能用到的格式串如下:

格式串 描述
%(name)s Logger 的名字
%(levelno)s 數字形式的日誌級別
%(levelname)s 文字形式的日誌級別
%(pathname)s 除錯日誌輸出函式的模式的完整路徑名,可能沒有
%(filename)s 除錯日誌輸出函式的模組的檔名
%(module)s 除錯日誌輸出函式的模組名
%(funcName)s 除錯日誌輸出函式的函式名
%(lineno)s 調式日誌輸出函式的語句所在的程式碼行
%(created)s 當前時間,用 UNIX 標準的表示時間的浮點數表示
%(relativeCreated)d 輸出日誌資訊時的,自 Logger 建立以來的毫秒數
%(asctime)s 字串形式的當前時間,預設格式是 "年-月-日 時:分:秒,毫秒"
%(thread)d 執行緒 ID,可能沒有
%(threadName)s 執行緒名,可能沒有
%(process)d 程序 ID,可能沒有
%(message)s 使用者輸出資訊
import logging

logging.basicConfig(
    # 日誌輸出位置:1、中斷 2、檔案
    filename="access.log",          # 不指定,預設列印到中斷

    # 日記格式:
    format="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s",

    # 時間格式
    datefmt="%Y-%m-%d %H:%M:%S %p",

    # 日記級別:critical(50) error(40) warning(30) info(20) debut(10)
    level=10,
)

logging.debug("debug除錯日誌")
logging.info("info訊息日誌")
logging.warning("warning警告日誌")
logging.error("error錯誤日誌")
logging.critical("critical嚴重日誌")

二、日誌字典的使用

  Python 3.2 中引入的一種新的配置日誌記錄的方法--用字典來儲存logging配置資訊。這相對於上面所講的基於配置檔案來儲存 logging 配置資訊的方式來說,功能更加強大,也更加靈活,因為我們可把很多的資料轉換成字典。

  傳遞給 dictConfig() 函式的字典物件只能包含下面這些 keys,其中 version 是必須指定的 key,其它 key 都是可選項:

key 名稱 描述
version 必選項,其值是一個整數值,表示配置格式的版本,當前唯一可用的值就是 1。
formatters 可選項,其值是一個字典對香港,該字典物件每個元素的 key 為要定義的格式器名稱,value 為格式器的配置資訊組成的 dict。
filters 可選項,其值是一個字典物件,該字典物件每個元素的 key 為要定義的過濾器名稱,value 為過濾器的配置資訊組成的 dict。
handlers 可選項,其值是一個字典物件,該字典物件每個元素的 key 為要定義的處理器名稱,value 為處理器的配置資訊組成的 dict。
loggers 可選項,其值是一個字典物件,該字典物件每個元素的 key 為要定義的日誌器名稱,value 為日誌器的配置資訊組成的 dict。
root 可選項,這是 root logger 的配置資訊,其值也是一個字典物件。除非咋定義其它 logger 時明確指定 propagate 值為 no,否則 root logger 定義的 handlers 都會被作用到其它 logger 上。
incremental 可選項,預設值為 False。該選項的意義在於,如果這裡定義的物件已經存在,那麼這裡對這些物件的定義是應用到以存在的物件上。值為 False 表示,以存在的物件將會被重新定義。
disable_existing_loggers 可選項,預設值為 True。該選項用於指定是否禁用以存在的日誌器 loggers,如果 incremental 的值為 True 則該選項將會被忽略。
# 定義日誌輸出格式開始
standard_format = "[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]" \
                "[%(levelname)s][%(message)s]"
simple_format = "[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s"

# log配置字典
LOGGING_DIC = {
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        # 自定義的日誌格式
        "standard": {
            "format": standard_format
        },
        "simple": {
            "format": simple_format
        },
    },
    "filters": {},                                              # 過濾日誌
    # handlers是日記的接收者,不同的handler會將日誌輸出到不同的位置
    "handlers": {
        # 列印到終端的日誌
        "console": {
            "level": "DEBUG",
            "class": "logging.StreamHandler",                   # 列印到螢幕
            "formatter": "simple"
        },
        # 列印到檔案的日誌,收集info及以上的日誌
        "default": {
            "level": "DEBUG",
            "class": "logging.handlers.RotatingFileHandler",    # 儲存到檔案
            "formatter": "standard",
            "filename": "access.log",                           # 日誌檔案檔案
            "maxBytes": 1024*1024*5,                            # 日誌檔案大小,達到大小後生成新的日誌檔案
            "backupCount": 5,                                   # 日誌檔案的個數
            "encoding": "utf-8",                                # 日誌檔案的編碼
        },
    },
    # loggers是日誌的產生著,產生的日誌會傳遞給handler然後控制輸出
    "loggers": {
        # logging.getLogger(__name__)拿到的logger配置
        "使用者交易": {
            # 這裡把上面定義的兩個handler都加上,即log資料既寫入檔案又列印到螢幕
            "handlers": ["default", "console"],  
            "level": "DEBUG",
            "propagate": False,                                 # 預設為True,向上(更高level的logger)傳遞
        },  

        # logging.getLogger(__name__)拿到的logger配置
        "": {
            # 這裡把上面定義的兩個handler都加上,即log資料既寫入檔案又列印到螢幕
            "handlers": ["default", "console"],  
            "level": "DEBUG",
            "propagate": False,                                 # 預設為True,向上(更高level的logger)傳遞
        },  
    },
}
import logging
import logging.config

logging.config.dictConfig(LOGGING_DIC)                         # logging模組載入字典中的配置

logger = logging.getLogger("使用者交易")                          # 獲取指定的日誌生產者
logger.debug("訂單生成")

# loggers配置中使用空字串作為字典的鍵 相容性最好
logger = logging.getLogger("常規操作")                          # 獲取指定的日誌生產者
logger.debug("使用者登入")