中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在python文件中調用logging模塊

發布時間:2021-05-11 16:07:45 來源:億速云 閱讀:202 作者:Leah 欄目:開發技術

本篇文章為大家展示了如何在python文件中調用logging模塊,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

python的五大特點是什么

python的五大特點:1.簡單易學,開發程序時,專注的是解決問題,而不是搞明白語言本身。2.面向對象,與其他主要的語言如C++和Java相比, Python以一種非常強大又簡單的方式實現面向對象編程。3.可移植性,Python程序無需修改就可以在各種平臺上運行。4.解釋性,Python語言寫的程序不需要編譯成二進制代碼,可以直接從源代碼運行程序。5.開源,Python是 FLOSS(自由/開放源碼軟件)之一。

有三個python模塊A、B、C。主模塊A會import B和C模塊,主模塊有對應的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的方式很簡單,創建一個RotatingFileHandler,通過RotatingFileHandler回滾logging的方式來控制LOG文件的個數和每個LOG文件的上限大小。并創建一個Formatter對象來設置LOG文件的格式。在程序中使用這種方式產生的logging對象來打LOG,很顯然使用這種方式的話,LOG都會打印到對應的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模塊對應的函數和類的時候并沒有直接用B的logging方式,而是對B logging進行了一個重定向,這個可以從SetLogger函數的作用可以函數。A直接會把已經logging對象傳給B,這樣B也可以和A共享同一個logging對象,并把LOG打到A設定的文件中。這對于一個主模塊調用多個子模塊的邏輯、而且每個子模塊都有對應的logging使用方式、打到不同文件中進行統一還是挺有好處的,這樣可以有效的控制總的LOG文件大小和數量。

但是沒有注意C模塊,然后發現的情況是,A程序在運行過程中會把A、B模塊的LOG信息直接打到屏幕上,而且LOG文件中也有對應的LOG。這些挺讓人困惑的,把對B模塊的調用注釋掉,依然會發現有A的LOG直接打到屏幕上。但是把A程序中設置logging對象的那段代碼單獨拿出來,一切都正常。

根據當時的情景,只能懷疑是C模塊中有什么設置,會導致A、B模塊打LOG的方式有些轉變。后來意識到,C模塊中并沒有設置logging的對象,而是直接使用logging.info去打LOG。把這部分的邏輯注釋掉,發現A、B打LOG的方式又恢復正常,再也不會往屏幕上打LOG。

通過參閱python logging模塊的代碼,發現一些有趣的現象:

1. logging對象其實是一個樹形結構,每個創建的logging對象都是root logging對象的孩子結點。當使用logging模塊的getLogger(name=None)函數構造logging對象的時候,如果name為None,這樣會產生一個root logging對象。如果name中含有.,比如name = 'a.b.c',通過這種方式會產生3個logging對象,分別為c、b、a,c->b->a->root,root樹的根結點,a為root的孩子結點,b為a的孩子結點,c為a的孩子結點,依次類推。

2. root結點是全局的,雖然這過程中涉及到多個模塊,但是它們會共享一個root結點。

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文件中有對應的LOG,但是屏幕中并沒有對象的顯示呢?

其實,如果對這個過程有些好奇,對直接很習以為常的方式有些懷疑,而且抱著這樣的好奇心去探索,相信肯定會有更多的收獲。

所以,比較困惑的是,為什么我調用A模塊產生的sLogger.info打出的LOG,只有LOG文件中有,而root logging為什么不打LOG打到屏幕上。為什么root logging不起作用。這個時候,可以看下logging __init__.py的代碼,會發現,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的方式有關。因此,print len(root.handlers),發現結果為0。也就是說,默認的root logging對應的handlers為[],這樣導致的結果是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

運行程序,得到如下運行結果:

0 []

1 [<logging.StreamHandler instance at 0x7f066e3eef80>]。


第一行結果為0 []很好的解釋了,為什么正常情況下,root logging對象為什么沒有打出LOG。

而調用logging.info('Bad')之后,root.handlers對象為StreamHandler對象。通過這個程序可以看到調用logging.info對象前后root logging對象發生的變化。

還有一點需要驗證,就是logging調用前后正常模塊logging的方式。

在__main__中寫下如下代碼:

if __name__ == '__main__':
 
  for i in xrange(0, 2):
 
    sLogger.info('OK')
 
    logging.info('Bad')

根據之前分析的,第一次調用sLogger.info('OK')是不會打LOG的,而logging.info本身是由于不到WARNING級別,所以也沒有打LOG,而第二次會打LOG在屏幕中。所以,看到的結果是,LOG文件中有三條LOG,而屏幕上有一條INFO:batch:OK。跟之前猜想到的挺吻合的。

 為什么調用了logging.info之后,會發生如此轉變?

繼續看完上面root logging info,并對照著下面的basicConfig代碼。會注意到len(root.handlers) == 0會去調用basicConfig,這個時候就可以注意下,basicConfig這個模塊的實現。

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)

上述內容就是如何在python文件中調用logging模塊,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

太仆寺旗| 宁夏| 海盐县| 安阳市| 淮滨县| 洞头县| 鄄城县| 巴彦县| 贺兰县| 濮阳市| 清苑县| 普定县| 明光市| 富蕴县| 土默特右旗| 绵阳市| 靖宇县| 监利县| 彭山县| 鄂尔多斯市| 贺州市| 民丰县| 定西市| 灵石县| 如皋市| 高青县| 汶川县| 田东县| 崇仁县| 瑞金市| 平湖市| 读书| 紫云| 乐至县| 蒙阴县| 孝昌县| 宜都市| 宁蒗| 施秉县| 阳朔县| 汤原县|