強(qiáng))DEBUG

亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

經(jīng)驗(yàn)拾憶(純手工)=> Python-logging模塊日志原理解析及使用

系統(tǒng) 1628 0

logging模塊

logging 模塊是一個(gè)較龐大的模塊。具有較完備的日志體系。
主要分為:主體 Logger - 處理器 - 格式器

logging 為 python 內(nèi)置模塊,無需安裝。
導(dǎo)入方式: import logging 即可

日志等級(jí)排序 (弱 -> 強(qiáng))

          
            DEBUG < INFO < WARNING < ERROR < FATAL

DEBUG :  開發(fā)調(diào)試的一些信息(print調(diào)試。。。)
INFO:    程序運(yùn)行過程的重要信息(不宜過多)
WARNING: 不影響程序運(yùn)行的小問題,警告一下。記錄下來以備以后解決。
ERROR:   影響程序, 有點(diǎn)嚴(yán)重。需要處理, 不然程序 (可能,可能)就掛了。
FATAL:   嚴(yán)重影響程序,立刻重新排查,修改代碼吧。

          
        

logging體系組件

常用分為: (由外到里的包含關(guān)系)

  1. Logger (主體日志)
    最大的容器,里面裝 Handler
  2. Handler (處理器類)
    里面裝 Formatter
  3. Formatter (格式器類)
    里面寫一些打印信息的格式語法

為了方便說明,接下來,我會(huì)把上面的組件“由里到外”講解。

Formatter(格式器類)

格式器:用來定義一些打印信息的字符串格式化的語法。
初始化一個(gè) 格式器:

          
            fmt = '[%(asctime)s] [%(filename)s: %(lineno)d] [%(levelname)s] => %(message)s' # 格式
console_formatter = logging.Formatter(fmt=fmt)   # 實(shí)例化格式器,并把格式傳進(jìn)來
          
        

理解方式:

  1. 我相信你只有 “格式”這行 看不明白,這格式你可以隨便搭配的, 見下方官方文檔有參數(shù)大全:
    官檔格式大全:https://docs.python.org/3.7/l...
  2. 打開官檔,你會(huì)看見表格的第二列 Format。 里面的格式直接原封不動(dòng)復(fù)制過來即可 eg: %(asctime)s
    然后,你把這些格式用字符串拼接成自己喜歡的符號(hào)格式即可, eg: "日期為 => %(asctime)s"
  3. 也許你會(huì)疑惑,為什么這種 %(..)s 的格式能被識(shí)別。 而不是被當(dāng)作原始字符串???
    注意第二行代碼, fmt格式字符串只是 Formatter() 的參數(shù),它里面會(huì)自動(dòng)被解析的。這你就別操心了。
  4. 我把上例結(jié)果貼一下,你可能會(huì)看明白些:

                  
                     >>> [2019-09-10 18:23:19,347] [logging11.py: 15] [WARNING] => 哈哈哈
          asctime   是日期        
          filename  是文件名  
          lineno    是代碼行
          levelname 是日志等級(jí)名 (就是上面說的 INFO WARNING ERROR之類的)
          message   是 你要打印的日志信息 (下面會(huì)講到,這里先小小埋一個(gè)點(diǎn))
    
                  
                

Handler(處理器類)

處理器:用來裝載上面說的 “格式器”,并處理日志 (處理器有很多種,按需選1個(gè)即可,下面說2種常用的):
初始化一個(gè) “流處理器” (比較常用):

          
            handler = logging.StreamHandler()
          
        

或初始化一個(gè) “文件處理器” (源碼明確寫了, 它繼承的是 上面的 “流處理器”。通常用來日志持久化):

          
            handler = logging.FileHandler('mylog.log', mode='a', encoding='utf-8')
# 不必解釋了吧。 這API語法很熟悉了吧。 這不就是我們常用的文件 open 語法么。。。。

          
        

裝載“格式器” (差點(diǎn)忘了吧。實(shí)例化的格式器,還沒用呢, 就是在這里裝載)

          
            handler.setFormatter(fmt=file_formatter)
          
        

注意: 雖然 handler對(duì)象就可以用 setLevel()設(shè)置日志等級(jí),但我不推薦在這里設(shè)置。繼續(xù)往下看

Logger(主體日志類)

Logger: 用來裝載 “處理器的”。

實(shí)例化Logger有兩種方法:
方法1:(非共享式創(chuàng)建, 不推薦)

          
            log= logging.Logger(name='my_log', level='INFO')    
# name 是給 Logger 起的名
# level是 日志等級(jí)(注意要大寫),   開篇我們講到過, WARNING, INFO, ERROR 這些。
          
        

方法2:(Log池共享式創(chuàng)建, 推薦)

          
            log = logging.getLogger(name='console')   
# 有則取出,無則創(chuàng)建
# name如果不傳,則取出root Logger  (root Logger是logging默認(rèn)給我們提供的,我一般不用)
          
        
說一下這兩種方法的區(qū)別:
  1. 非共享式: 即為每次都需要重新創(chuàng)建。從0開始配置
  2. Log池共享式: 從Log池取出索引來操作(就相當(dāng)于函數(shù)傳索引操作)
    你每對(duì)取出的Log做出配置時(shí),都會(huì)映射保存更新到 Log池 中。
    當(dāng)下次(或其他文件, 當(dāng)然是一個(gè)完整的程序)調(diào)用 getLogger() 取出的 log,就是之前我們配好的。

裝載 "處理器" :(差點(diǎn)忘了吧, 上面定義的 處理器,還沒用呢, 就是在這里用的):

          
            log.addHandler(handler)
          
        

設(shè)置日志等級(jí) (這步可忽略)

          
            log.setLevel('ERROR')

其實(shí)上面我們實(shí)例化Logger的時(shí)候,我們就已經(jīng)傳了一個(gè) level參數(shù),設(shè)置好了 日志等級(jí)。
所以 log.setLevel() 這個(gè)可以不設(shè)置 (包括前面提到,handler也有 setLevel)
     handler.setLevel()

          
        

開始輸出日志信息,有以下日志等級(jí)相對(duì)應(yīng)的API:

          
            log.debug  ("這是一條 調(diào)試 日志")
log.info   ("這是一條 顯示主要信息 日志")
log.warning('這是一條 警告 日志')
log.error  ("這是一條 錯(cuò)誤 日志")
log.fatal  ("這是一條 致命錯(cuò)誤 日志")

### 回顧我們前面講的 Formatter 格式器
我們第一個(gè)講的就是格式器, 并說了一下常用格式。
其中有個(gè) %(message)s,  它就是占位上面這些API里面的參數(shù)
    eg: log.info('哈哈哈')     
        %(message)s格式 占位輸出的就是   哈哈哈
    
還有個(gè)  %(levelname)s,它就是占位上面這些API的方法名
    eg: log.info('xxx')
         %(levelname)s 格式占位輸出的就是  info
          
        
如果你對(duì)日志等級(jí)與日志的作用感到模糊,你一定要看我接下來的例子?。。。。。。。?
開篇時(shí)我就提過: 日志等級(jí)排序(弱=>強(qiáng)) => (DEBUG < INFO < WARNING < ERROR < FATAL)

你設(shè)置了一個(gè)日志等級(jí) 。那么你所用上面API對(duì)應(yīng)的等級(jí)若“強(qiáng)于或等于” 此設(shè)定的等級(jí),日志才會(huì)被處理
emmmmm, 如果沒聽懂,就當(dāng)我放P了。。。 說的越正式,越不容易理解。 我們還是看下面的例子吧~~

日志等級(jí)理解的小例子:

          
            log.setLevel('WARNING')   你看我們?cè)O(shè)置的日志等級(jí)是 WARNING


log.debug("這是一條 調(diào)試 日志")    
    # 這個(gè) debug(),  你可以去開篇列的"日志等級(jí)排序"那里瞅一眼。
    # debug 比 warning 弱, 所以 這條日志是 不會(huì) 被處理的。
    # (白話理解:"我給的界限是warning, 你一個(gè) debug等級(jí)太低了,問題不嚴(yán)重。不配被記錄。")
    
log.info("這是一條 顯示主要信息 日志")
    # 同理, info 也比 warning 弱, 此條日志也 不會(huì) 被處理
    
log.warning('這是一條 警告 日志')
    # warning == warning (我前面說了,強(qiáng)于 或 等于) 所以此條日志會(huì)被處理
    
log.error("這是一條 錯(cuò)誤 日志")
    # error 比 warning 強(qiáng), 所以此條日志 會(huì) 被處理

log.fatal("這是一條 致命錯(cuò)誤 日志")
    # fatal 比  warning 強(qiáng), 所以此條日志 會(huì) 被處理
    # 再白話一下:"你給我的容忍程度是 warning, 而你的這條日志都致命錯(cuò)誤了,我肯定處理你啊"

          
        

思考!上例我一直說一句話 “xxxxx, 此條日志才會(huì)被處理”。
那么這個(gè)“ 處理” ,到底是處理什么呢???
這時(shí)不妨回頭看看,上面講的 “處理器”, 嗯, 沒錯(cuò)。 這些日志就是 “處理器” 處理的。

  1. 你要是定義一個(gè)流處理器(logging.StreamHandler), 它就會(huì)把日志輸出到終端。
  2. 你要是定義一個(gè)文件處理器(logging.FileHandler), 它就會(huì)自動(dòng)把日志保存到文件中,做持久化

綜合案例:

業(yè)務(wù)需求如下(隨便舉個(gè)案例,不一定有用):

  1. 比 DEBUG(強(qiáng)), 但又比 WARNING(弱) ,(不包括 WARNING) 的這類日志,只輸出到終端。
    這類日志輸出格式無要求
  2. 比 WARNING(強(qiáng)) (包括 WARNING )的這類日志, 輸出到 終端和文件 各一份。
    這類日志輸出格式有要求,格式為: [日期] [所在文件名: 代碼所在行] [日志級(jí)別] => 日志內(nèi)容

代碼如下(自己使用的話,封裝一下比較好):

          
            import logging
# 日志等級(jí)排序(弱-> 強(qiáng)): DEBUG < INFO < WARNING < ERROR < FATAL

fmt = '[%(asctime)s] [%(filename)s: %(lineno)d] [%(levelname)s] => %(message)s'  # 格式
file_formatter = logging.Formatter(fmt=fmt)    # 定義格式器, 把格式塞進(jìn)來
file_handler = logging.FileHandler('mylog.log', mode='a', encoding='utf-8')  # 定義文件處理器
file_handler.setFormatter(fmt=file_formatter)  # 給文件處理器設(shè)置 一個(gè) 格式器
file_handler.setLevel('WARNING')               # 給此處理器設(shè)置 日志等級(jí)


console_handler = logging.StreamHandler()      # 定義流處理器,用于輸出到終端 
# StreamHandler未設(shè)置格式器,它會(huì)默認(rèn)給你設(shè)置一個(gè) %(message)s,即只有日志內(nèi)容,沒有日期文件名等 
console_handler.setLevel('DEBUG')              # 給流處理器設(shè)置 日志等級(jí)

log = logging.getLogger(name='file_log')          # log池中取出一個(gè)log(若沒有則新建)   
log.addHandler(file_handler)                   # 添加一個(gè)文件處理器(格式化 輸出到 文件)
log.addHandler(console_handler)                # 再添加一個(gè)流處理器(無格式 輸出到 終端)

log.info('我只會(huì)輸出到終端')     # 因?yàn)?info只比 console_handler 設(shè)置的 DEBUG強(qiáng)
log.error('我既會(huì)輸出到終端, 又會(huì)輸出到文件')
# 因?yàn)閑rror 比 console_handler 設(shè)置的 DEBUG 強(qiáng), 同時(shí) error 也比 file_handler 設(shè)置的 WARNING 強(qiáng)
          
        

運(yùn)行結(jié)果:

          
            終端輸出:
>> 我只會(huì)輸出到終端
   我既會(huì)輸出到終端, 又會(huì)輸出到文件

mylog.log 文件中:
    [2019-09-10 23:54:59,055] [logging11.py: 20] [ERROR] => 我既會(huì)輸出到終端, 又會(huì)輸出到文件
          
        

----------------------華麗分割線----------------

投機(jī)取巧方式 (不推薦,這里開始往后,可不看)

這種方式只方便了一點(diǎn)點(diǎn),但不靈活。

前面我們花了好大力氣,

  1. 先是定義了一個(gè) 格式器
  2. 又是定義了一個(gè) 流處理器 和 文件處理器
  3. Logger池中,實(shí)例化一個(gè) Logger
  4. 并且把他們各種拼裝, 設(shè)置日志等級(jí)。等操作 (雖然看起來很多。其實(shí)你捋通了。真的不復(fù)雜)

其實(shí) logging體系中, 有一個(gè)默認(rèn)初始的 Logger, 叫做 root Logger.
我們不需要實(shí)例化它,也不需要實(shí)例化"格式器", 也不需要實(shí)例化控制器。
一行API就可以使用它 (默認(rèn)是輸出到終端的):

          
            import logging

fmt = '[%(asctime)s] [%(filename)s: %(lineno)d] [%(levelname)s] => %(message)s'  # 格式

logging.basicConfig(    # 默認(rèn)使用的就是 root Logger
    level='DEBUG',      # 設(shè)置日志等級(jí)為DEBUG
    format=fmt,         # 設(shè)置格式
)
logging.info('我只會(huì)輸出到終端')


運(yùn)行結(jié)果:
>> [2019-09-11 00:15:55,219] [logging11.py: 30] [INFO] => 我只會(huì)輸出到終端

          
        

如果想輸出到文件,那么只需加 filename 和 filemode 兩個(gè)參數(shù)即可:

          
            import logging

fmt = '[%(asctime)s] [%(filename)s: %(lineno)d] [%(levelname)s] => %(message)s'  # 格式

logging.basicConfig(
    level='DEBUG',
    format=fmt,
    filename='mylog.log',   # 文件名
    filemode='a'            # 文件操作符
)

運(yùn)行結(jié)果:
mylog.log文件:
    [2019-09-11 00:20:22,396] [logging11.py: 32] [INFO] => ?????????????
          
        

但你發(fā)現(xiàn)沒,往文件里面輸出亂碼了, 用耳朵都能想出來,我們沒有配置 encoding。。。
但是,我告訴你, basicConfig() 是沒有 encoding參數(shù)的。 那咋整 ??
但它有個(gè)參數(shù)叫做 handlers,handlers熟悉吧,沒錯(cuò)就是我們上面講的 "處理器", 復(fù)數(shù)說明可以傳多個(gè)

          
            logging.basicConfig(
    level='DEBUG',
    format=fmt,
    handlers=[ logging.FileHandler(filename='mylog.log',mode='a',encoding='utf-8') ]
    # 看這里這個(gè)處理器的定義方法,和之前講過的一模一樣。在這里我們可以配 encoding
)
# 這樣就不會(huì)亂碼了
          
        
Note: 以上就是用 logging.baseConfig() 簡(jiǎn)單日志實(shí)現(xiàn)
說了它是投機(jī)取巧,因?yàn)槌宋募y碼有問題之外, 它還欠缺靈活性。
比如你想想對(duì)不同級(jí)別的日志,用不同格式輸出出來。這時(shí)你單用basicConfig一行是搞不定的。
所以還是推薦用 getLogger()那套組合。

結(jié)束語

logging模塊其實(shí)還有很多很多功能:
過濾器:(其實(shí)還有個(gè)這個(gè)組件,但我沒用過,就沒說)
格式器:(前面給了官檔大全,里面還有根據(jù)進(jìn)程、線程的(PID,TID, tName,pName)等格式來輸出日志。)
控制器:(我只說了 stream 和 file),其實(shí)還有很多,它們都在logging.handlers模塊下:

          
            from logging.handlers import (
    RotatingFileHandler,       # 通過設(shè)置文件大小閾值,超出這個(gè)閾值,就會(huì)將日志轉(zhuǎn)存新文件
    TimedRotatingFileHandler,  # 設(shè)置時(shí)間間隔,每過這個(gè)間隔,就會(huì)將日志轉(zhuǎn)存新文件
    HTTPHandler,               # 通過HTTP協(xié)議將日志輸出到遠(yuǎn)程服務(wù)器,(只支持 GET 和 POST)
    SMTPHandler,               # 通過SMTP協(xié)議,將日志輸出到遠(yuǎn)程郵箱了
    SocketHandler,             # 通過TCP協(xié)議發(fā)送到遠(yuǎn)程服務(wù)器。。。
    DatagramHandler,           # 通過UDP協(xié)議發(fā)送到遠(yuǎn)程服務(wù)器。。。
    QueueHandler,              # 發(fā)到隊(duì)列中(如果想發(fā)RabbitMQ之類的,可以去github找別人寫的成品)
)
# 這些用法也很簡(jiǎn)單,看官檔,或者用Pycharm ctrl+左鍵點(diǎn)進(jìn)源碼,看一下__init__()參數(shù)實(shí)例化即可
# 實(shí)例化后,用 xxx.addHandler() 添加到 logger即可使用  (和前面講的 file和stream用法一樣)

          
        

還可做成各類型配置文件使用:https://docs.python.org/3/lib...
官檔案例大全:https://docs.python.org/3/how...


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會(huì)非常 感謝您的哦?。。?/p>

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 亚洲毛片一级带毛片基地 | 亚州在线播放 | 欧美高清激情毛片 | 国产精品人人 | 毛片99| 一级白嫩美女毛片免费 | 色国产在线视频一区 | 蜜桃综合 | 天天干天天曰天天操 | 国产不卡视频在线播放 | 国产一在线精品一区在线观看 | 99在线在线视频免费视频观看 | 久久国产精品亚洲 | 亚洲成a| 国产精品亚洲精品观看不卡 | 日本不卡一区二区三区 | yellow中文字幕久久网 | 女女女女女女bbbbbb级毛片 | 国产成人精品magnet | 五月激情综合网 | 九九99香蕉在线视频免费 | 全免费毛片在线播放 | 亚洲视频a | 天天综合亚洲国产色 | 欧美7777| 尤物福利在线 | 一级黄色影片 | 五月亭亭免费高清在线 | 一区二区三区视频观看 | 在线播放国产一区二区三区 | 搡女人免费的视频 | 一级黄色a毛片 | 特黄级| 国产成年网站 | 狠狠地射 | 久久黄色免费视频 | 一级片在线免费看 | 欧美理论大片清免费观看 | 夜夜超b天天 | 久久综合久久鬼色 | 国产精品_国产精品_国产精品 |