刚知道tornado原来是facebook开源的。
logging的简单介绍和使用
python内置模块logging,用于记录日志,格式化输出。通过getLogger()
获得的是单例且线程安全的(进程不安全),下文会简单介绍logging的常用方法和简单logging源码分析,以及tornado中的日志模块。
使用basicConfig()
(给root handler添加基本配置),除了level
和filename
参数外还有filemode
(默认a),format
(输出格式),handlers
(给root logger添加handlers)
import logging
logging.basicConfig(level=logging.DEBUG, filename='main.log')
logging.debug('bug log')
logging的日志分为这几种级别:
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
logging.info()
等实际上是根looger(root logger)的info()方法。
利用logger
的相对应的info
,debug
,waring
等可以输出日志,只有当方法级别>日志级别时才能够输出(如level=logging.INFO
时,用logging.error('error')
能够输出,而logging.debug('debug')
无输出)。
值得一提的是还有一个logging.exception()
方法,能够简单的记录Traceback信息(实际上是相当于logging.error(e, exc_info=True)
),所有的输出方法最终都是调用了logger的_log()
方法。
getLogger()
import logging
root_logger = logging.getLogger()
mine_logger = logging.getLogger('mine')
参数缺省时默认获取的是root_logger
,是所有logger的最终父logger。
在未作任何配置时,root_logger
的日志级别是warning
。
阅读getLogger()
源码可以发现
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
执行logging.getLogger('mine')
方法,即Manager(Logger.root).getLogger('mine')
,再来看一下Manager
的getLogger()
。
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.logg