在Flask框架中,每处理完一条请求,都会在终端打印出一条请求的日志信息:
127.0.0.1 - - [31/May/2018 04:40:35] "POST /xxx/xxx/xxx HTTP/1.1" 200 -
之所以打印了这条日志信息,是因为Flask框架在处理完请求后,调用了werkzeug库的_log函数,函数如下。
def _log(type, message, *args, **kwargs):
"""Log into the internal werkzeug logger."""
global _logger
if _logger is None:
import logging
_logger = logging.getLogger('werkzeug')
# Only set up a default log handler if the
# end-user application didn't set anything up.
if not logging.root.handlers and _logger.level == logging.NOTSET:
_logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
_logger.addHandler(handler)
getattr(_logger, type)(message.rstrip(), *args, **kwargs)
如果想要修改打印日志,可以在启动Flask之前,定义一个root logger
import logging
logger = logging.getLogger()
file_handler = logging.FileHandler('/path/to/log/test.log')
logger.addHandler(file_handler)
logger.setLevel(logging.INFO)
app.run()
这么做之所以能改变Flask打印信息的地方,是因为在_log函数中有个一条判断:
if not logging.root.handlers and _logger.level == logging.NOTSET
当在代码中定义了一个root logger即调用logging.getLogger()不传名字参数),该条件判断便不成立,因此,werkzeug中的 _logger = logging.getLogger(‘werkzeug’)便不会添加一个StreamHandler处理类。
另外,root logger实例的配置行为会影响带名字logger实例的行为
logger1 = logging.getLogger() # root logger
logger2 = logging.getLogger('hawk') # hawk logger
file_handler = logging.FileHandler('/usr/local/usersystem/user.log')
logger1.addHandler(file_handler)
logger1.setLevel(logging.INFO)
# 此时,当调用logger2时,logger2也会向日志文件中写入内容
基于这个机制,Werkzeug中的_logger便会按照你定义的root logger的行为进行写日志动作!