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

溫馨提示×

溫馨提示×

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

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

怎么在Python中打印日志中的logging.getLogger

發布時間:2021-01-18 14:41:36 來源:億速云 閱讀:217 作者:Leah 欄目:開發技術

本篇文章給大家分享的是有關怎么在Python中打印日志中的logging.getLogger,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

實踐環境

WIN 10

Python 3.6.5

函數說明

logging.getLogger(name=None)

getLogger函數位于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

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

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

該函數位于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
 
  # ... 略

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

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

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

_fixupParents及_fixupChildren函數源碼分析

# _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) # 創建PlaceHolder實例作為 點分上級 對應的日志打印器 # 繼續查找點分上級日志打印器 # 注意,這里的PlaceHolder僅是占位用,不是真的打印器,這里為了方便描述,暫且稱之為PlaceHolder日志打印器
      else: # 否則
        obj = self.loggerDict[substr] # 獲取 點分上級 對應的日志打印器
        if isinstance(obj, Logger): # 如果為Logger實例,如果是,則跳出循環,執行 # 為日志打印器設置上級
          rv = obj
        else: # 否則
          assert isinstance(obj, PlaceHolder) # 斷言它為PlaceHolder的實例
          obj.append(alogger) # 把日志打印器添加為點分上級對應的PlaceHolder日志打印器實例的下級日志打印器 執行 # 繼續查找點分上級日志打印器
      i = name.rfind(".", 0, i - 1) # 繼續查找點分上級日志打印器
    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日志打印器的上級

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

以上就是怎么在Python中打印日志中的logging.getLogger,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

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

AI

平南县| 临城县| 苍梧县| 望城县| 张家港市| 合阳县| 临夏市| 岱山县| 巴林右旗| 六枝特区| 台安县| 康马县| 喀喇| 温州市| 县级市| 广州市| 张掖市| 吐鲁番市| 延津县| 稻城县| 高陵县| 高台县| 兴海县| 界首市| 抚州市| 陆河县| 宜君县| 兰考县| 阳东县| 花垣县| 神木县| 攀枝花市| 阜新市| 华亭县| 永登县| 东海县| 玉溪市| 长海县| 眉山市| 霍林郭勒市| 呈贡县|