本次分析一下Logger.info的流程
1. Logger.info源碼:
def info(self, msg, *args, **kwargs): """ Log 'msg % args' with severity 'INFO'. To pass exception information, use the keyword argument exc_info with a true value, e.g. logger.info("Houston, we have a %s", "interesting problem", exc_info=1) """ if self.isEnabledFor(INFO): self._log(INFO, msg, args, **kwargs)
注釋中反應了可以通過 msg和不定參數args來進行日志的格式化。
真實的調用為:_log方法:
2. Logger._log方法:
def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False): """ Low-level logging routine which creates a LogRecord and then calls all the handlers of this logger to handle the record. """ sinfo = None if _srcfile: #IronPython doesn't track Python frames, so findCaller raises an #exception on some versions of IronPython. We trap it here so that #IronPython can use logging. try: fn, lno, func, sinfo = self.findCaller(stack_info) except ValueError: # pragma: no cover fn, lno, func = "(unknown file)", 0, "(unknown function)" else: # pragma: no cover fn, lno, func = "(unknown file)", 0, "(unknown function)" if exc_info: if isinstance(exc_info, BaseException): exc_info = (type(exc_info), exc_info, exc_info.__traceback__) elif not isinstance(exc_info, tuple): exc_info = sys.exc_info() record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra, sinfo) self.handle(record)
最后兩行:
生成日志記錄:
record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra, sinfo)
處理日志記錄
self.handle(record)
2 生成日志記錄:
def makeRecord(self, name, level, fn, lno, msg, args, exc_info, func=None, extra=None, sinfo=None): """ A factory method which can be overridden in subclasses to create specialized LogRecords. """ rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func, sinfo) if extra is not None: for key in extra: if (key in ["message", "asctime"]) or (key in rv.__dict__): raise KeyError("Attempt to overwrite %r in LogRecord" % key) rv.__dict__[key] = extra[key] return rv
調用_logRecordFactory初始化一個日志記錄實例,_logRecordFactory 其實就是LogRecord類,初始化時,可能包含logger的name, level、調用的函數、行號、日志字符串、模板參數、堆棧信息等。
再看extra信息,extra到底有何用?現在從代碼中可以看到,只是更新到生成的日志記錄實例的__dict__中去.猜測:肯定會在生成最終的日志字符串的時候會用到。繼續往下看。
3 處理日志記錄self.handle(record):
Logger繼承自Filterer,
def handle(self, record): """ Call the handlers for the specified record. This method is used for unpickled records received from a socket, as well as those created locally. Logger-level filtering is applied. """ if (not self.disabled) and self.filter(record): self.callHandlers(record)
|
新聞熱點
疑難解答