python logging 用法(一)

抽象組成

  1. Logger: 寫日志接口,把要記錄的日志發(fā)給它就好,要不要打印,打到哪里,用什么格式都被封裝進(jìn)去了.
  2. Handler: 用于封裝一個日志寫出方向
  • 寫console的handler: logging.StreamHandler()
  • 寫文件的handler: 如 handlers.TimedRotatingFileHandler
  1. Formatter: 用于定義一個日志打印格式, 綁定在一個handler上
    其中,%(asctime)s用于控制日志中時間在哪個位置顯示,
    時間格式由datefmt參數(shù)控制,但毫秒不在asctime中控制;
    %(msecs)d 用于毫秒部分的顯示控制,d是顯示幾位毫秒
    日志格式: https://docs.python.org/3.11/library/logging.html#logrecord-attributes
    時間格式: https://docs.python.org/3.11/library/time.html#time.strftime
  2. Filter: 用于定義一個日志過濾條件

這幾個之間具有這樣的組合關(guān)系


image.png

logger執(zhí)行流程

logging 執(zhí)行流程

Logger 和 Handler 都可以 setLevel, 都可以 addFilter

日志等級(不過多展開了)

  • 是個整數(shù), 越大等級越高
  • 默認(rèn)設(shè)置打印等級后,等于和高于打印等級的日志會被打印
  • logging. NOTSET < logging.DEBUG < logging.INFO < logging.WARNING < logging.ERROR < logging.CRITICAL

logger層級(todo: 下一篇)

其中名稱為 "root" 的 logger 比較特殊,是根 logger

用法Demo

import logging
import os
import sys
from logging import handlers

# 日志目錄
log_dir = os.getenv("app_logs", "./logs/")
if not os.path.exists(log_dir):
    os.makedirs(log_dir)

info_log_name = "info.log"
error_log_name = "error.log"

# 日志格式
log_fmt = "%(asctime)s.%(msecs)03d [%(process)d-%(thread)d] %(filename)s:%(lineno)d %(funcName)s " \
          "[%(levelname)s] %(message)s"
date_fmt = "%Y-%m-%d %H:%M:%S"
formatter = logging.Formatter(fmt=log_fmt, datefmt=date_fmt)


# filter

# 只保留非錯誤級別的日志
class NormalLogFilter(logging.Filter):
    def __init__(self, name):
        super().__init__(name=name)

    def filter(self, record: logging.LogRecord) -> bool:
        if record.levelno < logging.ERROR:
            return True
        return False


# handler

# 打印到控制臺(默認(rèn)輸出到標(biāo)準(zhǔn)錯誤流 sys.stderr)
console_handler = logging.StreamHandler(stream=sys.stdout)
console_handler.setFormatter(formatter)
console_handler.setLevel(logging.DEBUG)

# info 日志打印到文件
info_log_file_handler = handlers.TimedRotatingFileHandler(
    filename=os.path.join(log_dir, info_log_name), when="midnight", backupCount=15, encoding="utf-8")
info_log_file_handler.setFormatter(formatter)
info_log_file_handler.setLevel(logging.INFO)
normal_filter = NormalLogFilter("normalFilter")
info_log_file_handler.addFilter(normal_filter)

# error 日志打印到文件
error_log_file_handler = handlers.TimedRotatingFileHandler(
    filename=os.path.join(log_dir, error_log_name), when="midnight", backupCount=15, encoding="utf-8")
error_log_file_handler.setFormatter(formatter)
error_log_file_handler.setLevel(logging.ERROR)

# 生成 logger
logger = logging.getLogger("root")
logger.addHandler(console_handler)
logger.addHandler(info_log_file_handler)
logger.addHandler(error_log_file_handler)
logger.setLevel(logging.INFO)


# ========= test code ======== #

def _log_use_test():
    logger.setLevel(logging.DEBUG)
    logger.debug("dddebug")
    logger.info("iiinfo")
    logger.warning("wwwarning")
    logger.error("eeerror")
    logger.critical("cccritical")
    logger.info("占位符用法: %s:%d, 哈哈哈:%f", "詞語", 12, 3.01)
    word, idx, weight = "中文", 23, 5.23
    logger.info(f"占位符用法: {word}:{idx}, 哈哈哈:{weight}")

    try:
        12 / 0
    except Exception as e:
        # 使用 logging 參數(shù)輸出異常
        logger.error("Houston, we have a %s", "major problem", exc_info=True)

    try:
        12 / 0
    except Exception as e:
        # 直接使用 logging 的 exception 函數(shù)輸出異常堆棧信息
        logger.exception("Houston, we have another %s. error= {}".format(e), "major problem")

    try:
        12 / 0
    except Exception as e:
        import traceback
        s = traceback.format_exc()
        # 使用 logging + traceback 模塊輸出異常
        logging.info("traceback: {}".format(s))

if __name__ == "__main__":
    _log_use_test()

生成的日志格式如下

2024-01-29 17:35:11.666 [18827-4788831744] log_conf.py:76 _log_use_test [DEBUG] dddebug
2024-01-29 17:35:11.667 [18827-4788831744] log_conf.py:77 _log_use_test [INFO] iiinfo
2024-01-29 17:35:11.669 [18827-4788831744] log_conf.py:78 _log_use_test [WARNING] wwwarning
2024-01-29 17:35:11.669 [18827-4788831744] log_conf.py:79 _log_use_test [ERROR] eeerror
2024-01-29 17:35:11.670 [18827-4788831744] log_conf.py:80 _log_use_test [CRITICAL] cccritical
2024-01-29 17:35:11.670 [18827-4788831744] log_conf.py:81 _log_use_test [INFO] 占位符用法: 詞語:12, 哈哈哈:3.010000
2024-01-29 17:35:11.671 [18827-4788831744] log_conf.py:83 _log_use_test [INFO] 占位符用法: 中文:23, 哈哈哈:5.23
2024-01-29 17:35:11.671 [18827-4788831744] log_conf.py:89 _log_use_test [ERROR] Houston, we have a major problem
Traceback (most recent call last):
  File "/Users/admin/git-repo/log_conf.py", line 86, in _log_use_test
    12 / 0
ZeroDivisionError: division by zero
2024-01-29 17:35:11.673 [18827-4788831744] log_conf.py:95 _log_use_test [ERROR] Houston, we have another major problem. error= division by zero
Traceback (most recent call last):
  File "/Users/admin/git-repo/log_conf.py", line 92, in _log_use_test
    12 / 0
ZeroDivisionError: division by zero
2024-01-29 17:35:11.673 [18827-4788831744] log_conf.py:103 _log_use_test [INFO] traceback: Traceback (most recent call last):
  File "/Users/admin/git-repo/log_conf.py", line 98, in _log_use_test
    12 / 0
ZeroDivisionError: division by zero
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嗅榕,一起剝皮案震驚了整個濱河市熔酷,隨后出現(xiàn)的幾起案子斋枢,更是在濱河造成了極大的恐慌,老刑警劉巖淆攻,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嘿架,居然都是意外死亡瓶珊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門耸彪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來伞芹,“玉大人,你說我怎么就攤上這事蝉娜〕希” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵召川,是天一觀的道長南缓。 經(jīng)常有香客問我,道長荧呐,這世上最難降的妖魔是什么汉形? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮倍阐,結(jié)果婚禮上概疆,老公的妹妹穿的比我還像新娘。我一直安慰自己峰搪,他們只是感情好岔冀,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著罢艾,像睡著了一般楣颠。 火紅的嫁衣襯著肌膚如雪尽纽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天童漩,我揣著相機(jī)與錄音弄贿,去河邊找鬼。 笑死矫膨,一個胖子當(dāng)著我的面吹牛差凹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播侧馅,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼危尿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了馁痴?” 一聲冷哼從身側(cè)響起谊娇,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎罗晕,沒想到半個月后济欢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡小渊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年法褥,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酬屉。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡半等,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呐萨,到底是詐尸還是另有隱情杀饵,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布垛吗,位于F島的核電站凹髓,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏怯屉。R本人自食惡果不足惜蔚舀,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锨络。 院中可真熱鬧赌躺,春花似錦、人聲如沸羡儿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至缅叠,卻和暖如春悄泥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肤粱。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工弹囚, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人领曼。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓鸥鹉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親庶骄。 傳聞我的和親對象是個殘疾皇子毁渗,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容