您好,登錄后才能下訂單哦!
Python Logging
原來真的遠(yuǎn)比我想象的要復(fù)雜很多很多,學(xué)習(xí)路線堪比git。但是又繞不過去,alternatives又少,所以必須要予以重視,踏踏實(shí)實(shí)認(rèn)認(rèn)真真的來好好學(xué)學(xué)才行。
學(xué)習(xí)Logging的目的:
簡單腳本還好,print足夠。
但是稍微復(fù)雜點(diǎn),哪怕是三四個(gè)文件加起來兩三百行代碼,調(diào)試也開始變復(fù)雜起來了。
再加上如果是后臺(tái)長期運(yùn)行的那種腳本,運(yùn)行信息的調(diào)查更是復(fù)雜起來。
一開始我還在各種查crontab
的日志查看,或者是python
后臺(tái)運(yùn)行查看,或者是python stdout
的獲取等等,全都找錯(cuò)了方向。
真正的解決方案在于正確的logging。
記錄好了的話,我不需要去找python的控制臺(tái)輸出stdout,也不需要找crontab的日志,只需要查看log文件即可。
下面是python的logging學(xué)習(xí)記錄。
最簡單的日志輸出(無文件記錄)
import logging logging.error("出現(xiàn)了錯(cuò)誤") logging.info("打印信息") logging.warning("警告信息")
首先,忘掉logging.info()! 忘掉logging.basicConfig()!
網(wǎng)上各種關(guān)于python logging的文章實(shí)在是太不體諒新手了,logging這么復(fù)雜的東西竟然想表現(xiàn)得很簡單,還用各種簡單的東西做假象。
實(shí)際上我們真正要用起來的日志,絕對是不會(huì)直接用logging.info()
和logging.basicConfig()
這樣的,這是此模塊的官方推出來迷惑人的——看似讓你一鍵上手,快速看到結(jié)果,但是跟實(shí)際真的不搭!
所以為了后面解釋起來輕松,必須先警告這點(diǎn):忘記它們倆!
記住,唯一要用到logging.
什么的,就只有logging.getLogger()
這一次。
了解logging的工作流
不想上流程圖一類的東西,那樣反而更迷糊。
簡單說吧:
logging
模塊是會(huì)自動(dòng)將你自定制的logger對象全局化
的,
也就是說,你在自己的模塊里只要定義了一次某個(gè)logger,比如叫l(wèi)og,那么只要是在同一個(gè)模塊中運(yùn)行的其他文件都能讀取到它。
比如說,你在主文件main.py中自定義了一個(gè)logger,可能設(shè)置了什么輸出文件、輸出格式什么的,然后你在main.py
中會(huì)引用一些別的文件或模塊,比如sub.py
,那么在這個(gè)sub.py中你什么都不用設(shè)置,只要用一句logger = logging.getLogger('之前在main.py定義的日志名')
即可獲得之前的一切自定義設(shè)置。
當(dāng)然,被調(diào)用的文件(先稱為子模塊)中,用logging.getLogger('日志名')
時(shí),最好在日志名后加一個(gè).子名稱
這樣的,比如main.sub。這樣輸出的時(shí)候就會(huì)顯示出來某條日志記錄是來自于這個(gè)文件里了。當(dāng)然,.前面的父級(jí)logger必須名字一致,是會(huì)被識(shí)別出來的!
然后,子日志還可以再子日志,甚至一個(gè)子模塊可以再讓所有函數(shù)各又一個(gè)子子日志,比如main.sub.func1這樣的。logging都會(huì)根據(jù).識(shí)別出來上下級(jí)關(guān)系的。
這樣一說,實(shí)際上也就是class類繼承的那種機(jī)制了。你按照父級(jí)名稱繼承,然后還可以改寫自己的新設(shè)置等。
了解了這些概念以后,才能來談代碼。實(shí)際上也就好理解多了。
設(shè)置logger的方法
看來看去,這篇文章說得比較全面也最清楚,以下很多都參考到它的內(nèi)容:Python 101: An Intro to logging
一般想要自定義一個(gè)logger,比如讓它輸出信息時(shí)按照什么格式顯示,輸出到哪個(gè)文件,要不要輸出到屏幕一類,有三種方法可以達(dá)到設(shè)置:
三種達(dá)到的目的都是一樣的,字典用的人很少也不方便,配置文件比較好用只是.ini的語法不是很方便讀,且不容易做到變量的動(dòng)態(tài)設(shè)置,所以一般直接在python代碼里寫就好。
常用設(shè)置語句
以下是程序主入口文件的通用寫法,注意,一定要在主入口定義好logger,這樣其他所有的子模塊才能夠繼承到。
# main.py import logging import otherMod2 # 等下會(huì)調(diào)用到的子模塊 def main(): """ 這個(gè)文件是程序的主入口 """ define_logger() log = logging.getLogger('exampleApp') # 輸出信息測試 logger.info("Program started") result = otherMod2.add(7, 8) # 這個(gè)是來自別的模塊的方法 logger.info("Done!") def define_logger(): logger = logging.getLogger("exampleApp") logger.setLevel(logging.INFO) # 設(shè)置輸出格式 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 設(shè)置日志文件處理器 fh = logging.FileHandler("new_snake.log") fh.setFormatter(formatter) # 為這個(gè)處理器添加格式 # 設(shè)置屏幕stdout輸出處理器 sh = logging.StreamHandler(stream=None) sh.setFormatter(formatter) # 把處理器加到logger上 logger.addHandler(fh) logger.addHandler(sh) if __name__ == "__main__": main()
下面是子模塊中的調(diào)用方法(很簡單):
# otherMod2.py import logging module_logger = logging.getLogger("exampleApp.otherMod2") def add(x, y): # 這里一句`getLogger`就繼承到父級(jí)的logger了 logger = logging.getLogger("exampleApp.otherMod2.add") # 輸出測試 logger.info("added %s and %s to get %s" % (x, y, x+y)) return x+y
注意,主文件中,在什么地方定義logger都可以,可以在main()里也可以在任何單獨(dú)的函數(shù)或類里,無所謂。只要在調(diào)用子模塊之前定義好了就可以了。一旦定義過,日志名就會(huì)被記下來,然后子模塊就可以輕松繼承到。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。