最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python日志打印里logging.getLogger源碼分析詳解

 更新時間:2021年01月17日 13:42:10   作者:授客  
在本篇文章里小編給大家整理的是一篇關于Python logging.getLogger源碼分析的相關內(nèi)容,有興趣的朋友們可以學習參考下。

實踐環(huán)境

WIN 10

Python 3.6.5

函數(shù)說明

logging.getLogger(name=None)

getLogger函數(shù)位于logging/__init__.py腳本

源碼分析

_loggerClass = Logger
# ...略
 
root = RootLogger(WARNING)
Logger.root = root
Logger.manager = Manager(Logger.root)
 
# ...略
 
def getLogger(name=None):
  """
  Return a logger with the specified name, creating it if necessary.
 
  If no name is specified, return the root logger.
  """
  if name:
    return Logger.manager.getLogger(name)
  else:
    return root

結論:如函數(shù)注釋所述,如果調(diào)用getLogger時,如果沒有指定函數(shù)參數(shù)(即要獲取的日志打印器名稱)或者參數(shù)值不為真,則默認返回root打印器

Logger.manager.getLogger(self, name)源碼分析

該函數(shù)位于logging/__init__.py腳本

class Manager(object):
  """
  There is [under normal circumstances] just one Manager instance, which
  holds the hierarchy of loggers.
  """
  def __init__(self, rootnode):
    """
    Initialize the manager with the root node of the logger hierarchy.
    """
    self.root = rootnode
    self.disable = 0
    self.emittedNoHandlerWarning = False
    self.loggerDict = {}
    self.loggerClass = None
    self.logRecordFactory = None
 
  def getLogger(self, name):
    """
    Get a logger with the specified name (channel name), creating it
    if it doesn't yet exist. This name is a dot-separated hierarchical
    name, such as "a", "a.b", "a.b.c" or similar.
 
    If a PlaceHolder existed for the specified name [i.e. the logger
    didn't exist but a child of it did], replace it with the created
    logger and fix up the parent/child references which pointed to the
    placeholder to now point to the logger.
    """
    rv = None
    if not isinstance(name, str):
      raise TypeError('A logger name must be a string')
    _acquireLock()
    try:
      if name in self.loggerDict:
        rv = self.loggerDict[name]
        if isinstance(rv, PlaceHolder):
          ph = rv
          rv = (self.loggerClass or _loggerClass)(name)
          rv.manager = self
          self.loggerDict[name] = rv
          self._fixupChildren(ph, rv)
          self._fixupParents(rv)
      else:
        rv = (self.loggerClass or _loggerClass)(name) # _loggerClass = Logger
        rv.manager = self
        self.loggerDict[name] = rv
        self._fixupParents(rv)
    finally:
      _releaseLock()
    return rv

Logger源碼分析

_nameToLevel = {
  'CRITICAL': CRITICAL,
  'FATAL': FATAL,
  'ERROR': ERROR,
  'WARN': WARNING,
  'WARNING': WARNING,
  'INFO': INFO,
  'DEBUG': DEBUG,
  'NOTSET': NOTSET,
}
 
# ...略
 
def _checkLevel(level):
  if isinstance(level, int):
    rv = level
  elif str(level) == level:
    if level not in _nameToLevel:
      raise ValueError("Unknown level: %r" % level)
    rv = _nameToLevel[level]
  else:
    raise TypeError("Level not an integer or a valid string: %r" % level)
  return rv
 
# ...略
class PlaceHolder(object):
  """
  PlaceHolder instances are used in the Manager logger hierarchy to take
  the place of nodes for which no loggers have been defined. This class is
  intended for internal use only and not as part of the public API.
  """
  def __init__(self, alogger):
    """
    Initialize with the specified logger being a child of this placeholder.
    """
    self.loggerMap = { alogger : None }
 
  def append(self, alogger):
    """
    Add the specified logger as a child of this placeholder.
    """
    if alogger not in self.loggerMap:
      self.loggerMap[alogger] = None
 
 
 
class Logger(Filterer):
  """
  Instances of the Logger class represent a single logging channel. A
  "logging channel" indicates an area of an application. Exactly how an
  "area" is defined is up to the application developer. Since an
  application can have any number of areas, logging channels are identified
  by a unique string. Application areas can be nested (e.g. an area
  of "input processing" might include sub-areas "read CSV files", "read
  XLS files" and "read Gnumeric files"). To cater for this natural nesting,
  channel names are organized into a namespace hierarchy where levels are
  separated by periods, much like the Java or Python package namespace. So
  in the instance given above, channel names might be "input" for the upper
  level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
  There is no arbitrary limit to the depth of nesting.
  """
  def __init__(self, name, level=NOTSET):
    """
    Initialize the logger with a name and an optional level.
    """
    Filterer.__init__(self)
    self.name = name
    self.level = _checkLevel(level)
    self.parent = None
    self.propagate = True
    self.handlers = []
    self.disabled = False
 
  # ... 略

結論:如果調(diào)用logging.getLogger()時,有指定日志打印器名稱,且名稱為真(不為空字符串,0,F(xiàn)alse等False值),

1)如果名稱為不存在的日志打印器名稱,則,且參數(shù)值為真,但是即要獲取的日志打印器名稱)或者參數(shù)值不為真,則創(chuàng)建一個名為給定參數(shù)值的日志打印器,該日志打印器,默認級別默認為NOTSET,disable_existing_loggers配置為False,propagate配置為True。然后在日志打印器字典中記錄該名稱和日志打印器的映射關系,接著調(diào)用 _fixupParents(創(chuàng)建的日志打印器實例)類實例方法--為日志打印器設置上級日志打印器,最后返回該日志打印器。

2)如果名稱已存在日志打印器名稱,則獲取該日志打印器,然后判斷日志打印器是否為PlaceHolder類實例,如果是,則創(chuàng)建一個名為所給參數(shù)值的日志打印器,同第1)點,該日志打印器,默認級別默認為NOTSET,disable_existing_loggers配置為False,propagate配置為True。然后在日志打印器字典中記錄該名稱和日志打印器的映射關系,接著調(diào)用 _fixupParents(創(chuàng)建的打印器實例)類實例方法,_fixupChildren(PlaceHolder類實例--根據(jù)名稱獲取的日志打印器,新建的日志打印器實例)--為新建日志打印器設置上級日志打印器,為PlaceHolder類實例現(xiàn)有下級PlaceHolder日志打印器實例重新設置上級日志打印器,最后返回該日志打印器。

_fixupParents及_fixupChildren函數(shù)源碼分析

# _fixupParents
 
# ...略
class Manager(object):
  # ...略
  def _fixupParents(self, alogger):
    """
    Ensure that there are either loggers or placeholders all the way
    from the specified logger to the root of the logger hierarchy.
    """
    name = alogger.name # 獲取日志打印器名稱
    i = name.rfind(".")
    rv = None # 存放alogger日志打印器的上級日志打印器
    while (i > 0) and not rv: # 如果名稱中存在英文的點,并且找到上級日志打印器
      substr = name[:i] # 獲取名稱中位于最后一個英文的點的左側字符串(暫且稱至為 點分上級)
      if substr not in self.loggerDict: # 如果 點分上級 不存在日志打印器字典中
        self.loggerDict[substr] = PlaceHolder(alogger) # 創(chuàng)建PlaceHolder實例作為 點分上級 對應的日志打印器 # 繼續(xù)查找點分上級日志打印器 # 注意,這里的PlaceHolder僅是占位用,不是真的打印器,這里為了方便描述,暫且稱之為PlaceHolder日志打印器
      else: # 否則
        obj = self.loggerDict[substr] # 獲取 點分上級 對應的日志打印器
        if isinstance(obj, Logger): # 如果為Logger實例,如果是,則跳出循環(huán),執(zhí)行 # 為日志打印器設置上級
          rv = obj
        else: # 否則
          assert isinstance(obj, PlaceHolder) # 斷言它為PlaceHolder的實例
          obj.append(alogger) # 把日志打印器添加為點分上級對應的PlaceHolder日志打印器實例的下級日志打印器 執(zhí)行 # 繼續(xù)查找點分上級日志打印器
      i = name.rfind(".", 0, i - 1) # 繼續(xù)查找點分上級日志打印器
    if not rv: # 找不到點分上級、或者遍歷完所有點分上級,都沒找到上級日志打印器
      rv = self.root # 則 把root日志打印器設置為alogger日志打印器的上級日志打印器
    alogger.parent = rv # 為日志打印器設置上級
 
 
 
  def _fixupChildren(self, ph, alogger):
    """
    Ensure that children of the placeholder ph are connected to the
    specified logger.
    """
    name = alogger.name # 獲取日志打印器名稱
    namelen = len(name) # 獲取日志打印器名稱長度
    for c in ph.loggerMap.keys(): # 遍歷獲取的PlaceHolder日志打印器實例的子級日志打印器
      #The if means ... if not c.parent.name.startswith(nm)
      if c.parent.name[:namelen] != name: # 如果PlaceHolder日志打印器實例名稱不以alogger日志打印器名稱為前綴,
        alogger.parent = c.parent # 那么,設置alogger日志打印器的上級日志打印器為PlaceHolder日志打印器
        c.parent = alogger # 設置alogger日志打印器為PlaceHolder日志打印器原有下級PlaceHolder日志打印器的上級

結論:日志打印器都是分父子級的,這個父子層級是怎么形成的,參見上述函數(shù)代碼注解

到此這篇關于Python日志打印里logging.getLogger源碼分析詳解的文章就介紹到這了,更多相關Python logging.getLogger源碼分析內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 三分鐘教會你用Python+OpenCV批量裁剪xml格式標注的圖片

    三分鐘教會你用Python+OpenCV批量裁剪xml格式標注的圖片

    最近學習網(wǎng)絡在線課程的過程中,為了方便課后復習,使用手機截取了大量的圖片,下面這篇文章主要給大家介紹了如何通過三分鐘教會你用Python+OpenCV批量裁剪xml格式標注圖片的相關資料,需要的朋友可以參考下
    2022-01-01
  • 使用numpy和PIL進行簡單的圖像處理方法

    使用numpy和PIL進行簡單的圖像處理方法

    今天小編就為大家分享一篇使用numpy和PIL進行簡單的圖像處理方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • Python中文糾錯的簡單實現(xiàn)

    Python中文糾錯的簡單實現(xiàn)

    這篇文章主要是用 Python 實現(xiàn)了簡單的中文分詞的同音字糾錯,目前的案例中只允許錯一個字,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 使用Python實現(xiàn)PDF頁面設置操作

    使用Python實現(xiàn)PDF頁面設置操作

    這篇文章主要為大家詳細介紹了如何使用Python實現(xiàn)PDF頁面設置操作,例如旋轉頁面和調(diào)整頁面順序,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-04-04
  • python實現(xiàn)實時監(jiān)控文件的方法

    python實現(xiàn)實時監(jiān)控文件的方法

    這篇文章主要為大家詳細介紹了python實現(xiàn)實時監(jiān)控文件的3種方法,感興趣的小伙伴們可以參考一下
    2016-08-08
  • java直接調(diào)用python腳本的例子

    java直接調(diào)用python腳本的例子

    有時需求使用JAVA直接調(diào)用python腳本,執(zhí)行一些服務器監(jiān)控的事情。 本文給出一個java直接調(diào)用python腳本的例子
    2014-02-02
  • django url到views參數(shù)傳遞的實例

    django url到views參數(shù)傳遞的實例

    今天小編就為大家分享一篇django url到views參數(shù)傳遞的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-07-07
  • Python實現(xiàn)時間序列變化點檢測功能

    Python實現(xiàn)時間序列變化點檢測功能

    平穩(wěn)性是時間序列分析與預測的核心概念,在平穩(wěn)條件下,時間序列的統(tǒng)計特性(如均值)在時間維度上保持不變,僅存在隨機波動,但是時間序列通常會經(jīng)歷結構性斷裂或變化,本文給大家介紹了Python實現(xiàn)時間序列變化點檢測功能,需要的朋友可以參考下
    2024-09-09
  • python借助ChatGPT讀取.env實現(xiàn)文件配置隔離保障私有數(shù)據(jù)安全

    python借助ChatGPT讀取.env實現(xiàn)文件配置隔離保障私有數(shù)據(jù)安全

    這篇文章主要為大家介紹了python讀取.env實現(xiàn)文件配置隔離保障私有數(shù)據(jù)安全,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • Python并行計算庫Joblib高效使用指北

    Python并行計算庫Joblib高效使用指北

    Joblib是用于高效并行計算的Python開源庫,其提供了簡單易用的內(nèi)存映射和并行計算的工具,以將任務分發(fā)到多個工作進程中,這篇文章主要介紹了Python并行計算庫Joblib使用指北,需要的朋友可以參考下
    2024-08-08

最新評論

崇左市| 靖边县| 宣威市| 河东区| 江达县| 富裕县| 延川县| 柳州市| 景洪市| 梨树县| 喀什市| 永济市| 曲沃县| 嘉善县| 二连浩特市| 广汉市| 旺苍县| 泰兴市| 留坝县| 樟树市| 浠水县| 长治市| 岳阳县| 永德县| 元谋县| 宜兰县| 南宫市| 道真| 伊宁县| 太仓市| 诏安县| 永嘉县| 华池县| 屏东市| 兴海县| 太保市| 疏附县| 周宁县| 尼勒克县| 吉木萨尔县| 鄄城县|