logging模块的四大组件
- Logger: 对象扮演了三重角色.首先,它暴露给应用几个方法以便应用可以在运行时写log. 其次,Logger对象按照log信息的严重程度或者根据filter对 象来决定如何处理log信息(默认的过滤功能).最后,logger还负责把log信息传送给相关的log handlers。可以通过logging.getLogger(name)获取logger对象,如果不指定name则返回root对象,多次使用相同的name调用getLogger方法返回同一个logger对象。
- Handler: 对象负责分配合适的log信息(基于log信息的严重 程度)到handler指定的目的地,比如文件,socket等。Logger对象可以用addHandler()方法添加零个或多个handler对象到它自身。一个常见的场景 是,一个应用可能希望把所有的log信息都发送到一个log文件中去,所有的error级别以上的log信息都发送到 stdout,所有critical 的log信息通过email发送。这个场景里要求三个不同handler处理,每个handler负责把特定的log信息发送到特定的地方。
- Filter: 细致化,选择哪些日志输出
- Formater: 设置显示格式
%(name)s Logger的名字
%(levelname)s 文本形式的日志级别
%(message)s 用户输出的消息
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(levelno)s 数字形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
日志级别
logger,handler和日志消息的调用可以有具体的日志级别(Level),只有在日志消息的级别大于logger和handler的级别。
日志等级(level) | 描述 |
---|---|
DEBUG | 最详细的日志信息,典型应用场景是 问题诊断 |
INFO | 信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作 |
WARNING | 当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的 |
ERROR | 由于一个更严重的问题导致某些功能不能正常运行时记录的信息 |
CRITICAL | 当发生严重错误,导致应用程序不能继续运行时记录的信息 |
使用
日志简单使用: logging.basicConfig([**kwargs])
Does basic configuration for the logging system by creating a StreamHandler with a defaultFormatter and adding it to the root logger. The functionsdebug(),info(),warning(),error() andcritical() will callbasicConfig() automatically if no handlers are defined for the root logger.
This function does nothing if the root logger already has handlers configured for it.
翻译:
通过使用defaultFormatter创建StreamHandler并将其添加到根记录器,为日志记录系统进行基本配置。如果没有为根记录器定义处理程序,functionsdebug(),info(),warning(),error()和critical()将自动调用basicConfig()。
如果根记录器已经为它配置了处理程序,该函数不会执行任何操作。
import logging
def test1():
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
filename='test.log',
level=logging.DEBUG,
filemode='w'
)
logging.info('hi')
logging.debug('hello')
test1()
日志文件内容:
2018-04-17 09:20:25,740 - root - INFO - hi
2018-04-17 09:20:25,740 - root - DEBUG - hello
logging模块日志流处理流程
import logging
def test2():
logger = logging.getLogger("simple_example")
logger.setLevel(logging.INFO)
# 设置日志格式
formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s")
# 建立一个filehandler来把日志记录在文件里,级别为debug以上
fh = logging.FileHandler("spam.log", mode='w')
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter) # 设置格式
# 建立一个streamhandler来把日志打在CMD窗口上,级别为error以上
ch = logging.StreamHandler()
ch.setLevel(logging.ERROR)
ch.setFormatter(formatter) # 设置格式
# 将相应的handler添加在logger对象中
logger.addHandler(ch)
logger.addHandler(fh)
# 开始打日志
logger.debug("debug message")
logger.info("info message")
logger.warn("warn message")
logger.error("error message")
logger.critical("critical message")
test2()
控制台输出:
2018-04-17 09:29:27,009 - __main__ - ERROR - error message
2018-04-17 09:29:27,009 - __main__ - CRITICAL - critical message
spam.log:
2018-04-17 09:38:21,802 - simple_example - INFO - info message
2018-04-17 09:38:21,802 - simple_example - WARNING - warn message
2018-04-17 09:38:21,802 - simple_example - ERROR - error message
2018-04-17 09:38:21,802 - simple_example - CRITICAL - critical message
filter使用
import logging
def test4():
# 创建2个logger
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)
logger2 = logging.getLogger('mylogger.child1')
logger2.setLevel(logging.WARNING)
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
# 定义handler的输出格式formatter
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
# 定义一个filter
# TODO
# 给logger添加handler
logger1.addHandler(ch)
logger2.addHandler(ch)
# 记录一条日志
logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')
logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')
test4()
输出:
2018-04-17 10:27:52,497 - mylogger - DEBUG - logger1 debug message
2018-04-17 10:27:52,497 - mylogger - INFO - logger1 info message
2018-04-17 10:27:52,497 - mylogger - WARNING - logger1 warning message
2018-04-17 10:27:52,497 - mylogger - ERROR - logger1 error message
2018-04-17 10:27:52,497 - mylogger - CRITICAL - logger1 critical message
2018-04-17 10:27:52,497 - mylogger.child1 - WARNING - logger2 warning message
2018-04-17 10:27:52,497 - mylogger.child1 - WARNING - logger2 warning message
2018-04-17 10:27:52,497 - mylogger.child1 - ERROR - logger2 error message
2018-04-17 10:27:52,497 - mylogger.child1 - ERROR - logger2 error message
2018-04-17 10:27:52,497 - mylogger.child1 - CRITICAL - logger2 critical message
2018-04-17 10:27:52,497 - mylogger.child1 - CRITICAL - logger2 critical message
在 TODO 处加上以下两句
filter = logging.Filter('mylogger.child1')
ch.addFilter(filter)
加上后输出:
2018-04-17 10:30:54,364 - mylogger.child1 - WARNING - logger2 warning message
2018-04-17 10:30:54,364 - mylogger.child1 - WARNING - logger2 warning message
2018-04-17 10:30:54,364 - mylogger.child1 - ERROR - logger2 error message
2018-04-17 10:30:54,364 - mylogger.child1 - ERROR - logger2 error message
2018-04-17 10:30:54,364 - mylogger.child1 - CRITICAL - logger2 critical message
2018-04-17 10:30:54,364 - mylogger.child1 - CRITICAL - logger2 critical message
log 配置
import logging.config
def test3():
# 日志的加载
logging.config.fileConfig("conf_log.txt")
root_logger = logging.getLogger('root')
root_logger.debug('debug')
test3()
输出:
2018-04-17 09:45:05,565 - root - DEBUG - debug
conf_log.txt 文件
[loggers]
keys=root
[handlers]
keys=consoleHandler
[formatters]
keys=fmt
[logger_root]
level=DEBUG
handlers=consoleHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=fmt
args=(sys.stdout,)
[formatter_fmt]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
参考文章:
python logging 日志使用
Python之日志处理(logging模块)
每个 Python 程序员都要知道的日志实践
Python中内置的日志模块logging用法详解
Django 如何使用logging打印日志