本篇文章為大家展示了如何在python文件中調(diào)用logging模塊,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
目前創(chuàng)新互聯(lián)公司已為上1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬主機、網(wǎng)站改版維護、企業(yè)網(wǎng)站設(shè)計、乳源網(wǎng)站維護等服務(wù),公司將堅持客戶導向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。python的五大特點:1.簡單易學,開發(fā)程序時,專注的是解決問題,而不是搞明白語言本身。2.面向?qū)ο?,與其他主要的語言如C++和Java相比, Python以一種非常強大又簡單的方式實現(xiàn)面向?qū)ο缶幊獭?.可移植性,Python程序無需修改就可以在各種平臺上運行。4.解釋性,Python語言寫的程序不需要編譯成二進制代碼,可以直接從源代碼運行程序。5.開源,Python是 FLOSS(自由/開放源碼軟件)之一。
有三個python模塊A、B、C。主模塊A會import B和C模塊,主模塊有對應(yīng)的logging方式,
A使用logging的模塊的方式為:
import logging import logging.handlers def CreateLogger(logFile = 'batch'): handler = logging.handlers.RotatingFileHandler(str(logFile) + '.LOG', maxBytes = 1024 * 1024 * 500, backupCount = 5) fmt = '%(asctime)s - %(filename)s:%(lineno)s - %(name)s - %(message)s' formatter = logging.Formatter(fmt) handler.setFormatter(formatter) logger = logging.getLogger(str(logFile)) logger.addHandler(handler) logger.setLevel(logging.INFO) return logger sLogger = CreateLogger()
其實A模塊使用logging的方式很簡單,創(chuàng)建一個RotatingFileHandler,通過RotatingFileHandler回滾logging的方式來控制LOG文件的個數(shù)和每個LOG文件的上限大小。并創(chuàng)建一個Formatter對象來設(shè)置LOG文件的格式。在程序中使用這種方式產(chǎn)生的logging對象來打LOG,很顯然使用這種方式的話,LOG都會打印到對應(yīng)的LOG文件中去。
B使用logging模塊的方式為
def GetLogger(testName): logger = logging.getLogger(testName) logger.setLevel(logging.INFO) hdlr = logging.FileHandler(testName + '.LOG') hdlr.setLevel(logging.INFO) formatter = logging.Formatter("[%(asctime)s]\t[%(levelname)s]\t[%(thread)d]\t[%(pathname)s:%(lineno)d]\t%(message)s") hdlr.setFormatter(formatter) logger.addHandler(hdlr) return logger logger = GetLogger('OK') def SetLogger(log): global logger logger = log
B模塊默認logging的方式跟A差不多,只是B選擇logging的方式是往一個LOG文件中打LOG。A其實在實際使用B模塊對應(yīng)的函數(shù)和類的時候并沒有直接用B的logging方式,而是對B logging進行了一個重定向,這個可以從SetLogger函數(shù)的作用可以函數(shù)。A直接會把已經(jīng)logging對象傳給B,這樣B也可以和A共享同一個logging對象,并把LOG打到A設(shè)定的文件中。這對于一個主模塊調(diào)用多個子模塊的邏輯、而且每個子模塊都有對應(yīng)的logging使用方式、打到不同文件中進行統(tǒng)一還是挺有好處的,這樣可以有效的控制總的LOG文件大小和數(shù)量。
但是沒有注意C模塊,然后發(fā)現(xiàn)的情況是,A程序在運行過程中會把A、B模塊的LOG信息直接打到屏幕上,而且LOG文件中也有對應(yīng)的LOG。這些挺讓人困惑的,把對B模塊的調(diào)用注釋掉,依然會發(fā)現(xiàn)有A的LOG直接打到屏幕上。但是把A程序中設(shè)置logging對象的那段代碼單獨拿出來,一切都正常。
根據(jù)當時的情景,只能懷疑是C模塊中有什么設(shè)置,會導致A、B模塊打LOG的方式有些轉(zhuǎn)變。后來意識到,C模塊中并沒有設(shè)置logging的對象,而是直接使用logging.info去打LOG。把這部分的邏輯注釋掉,發(fā)現(xiàn)A、B打LOG的方式又恢復正常,再也不會往屏幕上打LOG。
通過參閱python logging模塊的代碼,發(fā)現(xiàn)一些有趣的現(xiàn)象:
1. logging對象其實是一個樹形結(jié)構(gòu),每個創(chuàng)建的logging對象都是root logging對象的孩子結(jié)點。當使用logging模塊的getLogger(name=None)函數(shù)構(gòu)造logging對象的時候,如果name為None,這樣會產(chǎn)生一個root logging對象。如果name中含有.,比如name = 'a.b.c',通過這種方式會產(chǎn)生3個logging對象,分別為c、b、a,c->b->a->root,root樹的根結(jié)點,a為root的孩子結(jié)點,b為a的孩子結(jié)點,c為a的孩子結(jié)點,依次類推。
2. root結(jié)點是全局的,雖然這過程中涉及到多個模塊,但是它們會共享一個root結(jié)點。
3. 每個logging對象打LOG的時候,也會把LOG信息傳遞到傳遞到上層logging對象中,對于c->b->a->root這種情況,這個LOG其實會打4次,以c、b、a、root循序依次打一個LOG。
可能有人會問,像我之前一般用A模塊或者B模塊那樣的方式去初始化一個logging對象,這樣初始化的對象也會是root logging對象的一個孩子,而root logging對象通常會把LOG打到屏幕上,那按理說,正常情況下打LOG都會打兩份,一份會打到文件中,一份會打到屏幕中。那為什么實際情況是,只有LOG文件中有對應(yīng)的LOG,但是屏幕中并沒有對象的顯示呢?
其實,如果對這個過程有些好奇,對直接很習以為常的方式有些懷疑,而且抱著這樣的好奇心去探索,相信肯定會有更多的收獲。
所以,比較困惑的是,為什么我調(diào)用A模塊產(chǎn)生的sLogger.info打出的LOG,只有LOG文件中有,而root logging為什么不打LOG打到屏幕上。為什么root logging不起作用。這個時候,可以看下logging __init__.py的代碼,會發(fā)現(xiàn),root logging info的代碼如下:
def info(msg, *args, **kwargs): """ Log a message with severity 'INFO' on the root logger. """ if len(root.handlers) == 0: basicConfig() root.info(msg, *args, **kwargs)
上面的代碼中涉及到root.handlers,懷疑root.handlers跟打LOG的方式有關(guān)。因此,print len(root.handlers),發(fā)現(xiàn)結(jié)果為0。也就是說,默認的root logging對應(yīng)的handlers為[],這樣導致的結(jié)果是sLogger打LOG的時候,root logging并不會打任何LOG。在__main__中添加如下代碼:
if __name__ == '__main__': sLogger.info('OK') print len(logging.root.handlers), logging.root.handlers logging.info('Bad') print len(logging.root.handlers), logging.root.handlers
運行程序,得到如下運行結(jié)果:
0 []
1 [<logging.StreamHandler instance at 0x7f066e3eef80>]。
第一行結(jié)果為0 []很好的解釋了,為什么正常情況下,root logging對象為什么沒有打出LOG。
而調(diào)用logging.info('Bad')之后,root.handlers對象為StreamHandler對象。通過這個程序可以看到調(diào)用logging.info對象前后root logging對象發(fā)生的變化。
還有一點需要驗證,就是logging調(diào)用前后正常模塊logging的方式。
在__main__中寫下如下代碼:
if __name__ == '__main__': for i in xrange(0, 2): sLogger.info('OK') logging.info('Bad')
根據(jù)之前分析的,第一次調(diào)用sLogger.info('OK')是不會打LOG的,而logging.info本身是由于不到WARNING級別,所以也沒有打LOG,而第二次會打LOG在屏幕中。所以,看到的結(jié)果是,LOG文件中有三條LOG,而屏幕上有一條INFO:batch:OK。跟之前猜想到的挺吻合的。
為什么調(diào)用了logging.info之后,會發(fā)生如此轉(zhuǎn)變?
繼續(xù)看完上面root logging info,并對照著下面的basicConfig代碼。會注意到len(root.handlers) == 0會去調(diào)用basicConfig,這個時候就可以注意下,basicConfig這個模塊的實現(xiàn)。
def basicConfig(**kwargs): if len(root.handlers) == 0: filename = kwargs.get("filename") if filename: mode = kwargs.get("filemode", 'a') hdlr = FileHandler(filename, mode) else: stream = kwargs.get("stream") hdlr = StreamHandler(stream) fs = kwargs.get("format", BASIC_FORMAT) dfs = kwargs.get("datefmt", None) fmt = Formatter(fs, dfs) hdlr.setFormatter(fmt) root.addHandler(hdlr) level = kwargs.get("level") if level is not None: root.setLevel(level)
上述內(nèi)容就是如何在python文件中調(diào)用logging模塊,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計公司行業(yè)資訊頻道。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
網(wǎng)站題目:如何在python文件中調(diào)用logging模塊-創(chuàng)新互聯(lián)
本文網(wǎng)址:http://jinyejixie.com/article30/csdeso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供靜態(tài)網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)、外貿(mào)建站、網(wǎng)站內(nèi)鏈、網(wǎng)站策劃、企業(yè)網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容