日志级别
级别对应的数值:
NOTSET(0)、DEBUG(10)、INFO(20)、WARNING(30)、ERROR(40)、CRITICAL(50)
INFO、WARNING、ERROR、CRITICAL 级别的日志都会输出
logging 流程
Logger:日志,暴露函数给应用程序,基于日志记录器和过滤器级别决定哪些日志有效。
LogRecord :日志记录器,将日志传到相应的处理器处理。
Handler :处理器, 将(日志记录器产生的)日志记录发送至合适的目的地。
Filter :过滤器, 提供了更好的粒度控制,它可以决定输出哪些日志记录。
Formatter:格式化器, 指明了最终输出中日志记录的布局
基本使用
参数名称 | 参数描述 |
---|---|
filename | 日志输出到文件的文件名 |
filemode | 文件模式,r[+]、w[+]、a[+] |
format | 日志输出的格式 |
datefat | 日志附带日期时间的格式 |
style | 格式占位符,默认为 “%” 和 “{}” |
level | 设置日志输出级别 |
stream | 定义输出流,用来初始化 StreamHandler 对象,不能 filename 参数一起使用,否则会ValueError 异常 |
handles | 定义处理器,用来创建 Handler 对象,不能和 filename 、stream 参数一起使用,否则也会抛出 ValueError 异常 |
常用变量格式如下
变量 | 格式 | 变量描述 |
---|---|---|
asctime | %(asctime)s | 将日志的时间构造成可读的形式,默认情况下是精确到毫秒,如 2018-10-13 23:24:57,832,可以额外指定 datefmt 参数来指定该变量的格式 |
name | %(name) | 日志对象的名称 |
filename | %(filename)s | 不包含路径的文件名 |
pathname | %(pathname)s | 包含路径的文件名 |
funcName | %(funcName)s | 日志记录所在的函数名 |
levelname | %(levelname)s | 日志的级别名称 |
message | %(message)s | 具体的日志信息 |
lineno | %(lineno)d | 日志记录所在的行号 |
pathname | %(pathname)s | 完整路径 |
process | %(process)d | 当前进程ID |
processName | %(processName)s | 当前进程名称 |
thread | %(thread)d | 当前线程ID |
threadName | %threadName)s | 当前线程名称 |
输出INFO
import logging
logging.basicConfig(format=‘%(asctime)s - %(pathname)s[line:%(lineno)d]- %(levelname)s:
%(message)s’, level=logging.INFO)
logging.debug(‘This is a debug message’)
logging.info(“距离是:{},{}”.format(self.des,self._pos))
关掉logging.info,把logging.basicConfig注释掉就可以了
自定义 Logger
上面的基本使用可以让我们快速上手 logging 模块,但一般并不能满足实际使用,我们还需要自定义 Logger。
一个系统只有一个 Logger 对象,并且该对象不能被直接实例化,没错,这里用到了单例模式,获取 Logger 对象的方法为 getLogger。
注意:这里的单例模式并不是说只有一个 Logger 对象,而是指整个系统只有一个根 Logger 对象,Logger 对象在执行 info()、error() 等方法时实际上调用都是根 Logger 对象对应的 info()、error() 等方法。
我们可以创造多个 Logger 对象,但是真正输出日志的是根 Logger 对象。每个 Logger 对象都可以设置一个名字,如果设置logger = logging.getLogger(name),name 是 Python 中的一个特殊内置变量,他代表当前模块的名称(默认为 main)。则 Logger 对象的 name 为建议使用使用以点号作为分隔符的命名空间等级制度。
Logger 对象可以设置多个 Handler 对象和 Filter 对象,Handler 对象又可以设置 Formatter 对象。Formatter 对象用来设置具体的输出格式,
Logger 对象和 Handler 对象都可以设置级别,而默认 Logger 对象级别为 30 ,也即 WARNING,默认 Handler 对象级别为 0,也即 NOTSET。logging 模块这样设计是为了更好的灵活性,比如有时候我们既想在控制台中输出DEBUG 级别的日志,又想在文件中输出WARNING级别的日志。可以只设置一个最低级别的 Logger 对象,两个不同级别的 Handler 对象,示例代码如下:
import logging
import logging.handlerslogger = logging.getLogger("logger")handler1 = logging.StreamHandler()
handler2 = logging.FileHandler(filename="test.log")logger.setLevel(logging.DEBUG)
handler1.setLevel(logging.WARNING)
handler2.setLevel(logging.DEBUG)formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
handler1.setFormatter(formatter)
handler2.setFormatter(formatter)logger.addHandler(handler1)
logger.addHandler(handler2)# 分别为 10、30、30
# print(handler1.level)
# print(handler2.level)
# print(logger.level)logger.debug('This is a customer debug message')
logger.info('This is an customer info message')
logger.warning('This is a customer warning message')
logger.error('This is an customer error message')
logger.critical('This is a customer critical message')
控制台输出结果为:
2018-10-13 23:24:57,832 logger WARNING This is a customer warning message
2018-10-13 23:24:57,832 logger ERROR This is an customer error message
2018-10-13 23:24:57,832 logger CRITICAL This is a customer critical message
文件中输出内容为:
2018-10-13 23:44:59,817 logger DEBUG This is a customer debug message
2018-10-13 23:44:59,817 logger INFO This is an customer info message
2018-10-13 23:44:59,817 logger WARNING This is a customer warning message
2018-10-13 23:44:59,817 logger ERROR This is an customer error message
2018-10-13 23:44:59,817 logger CRITICAL This is a customer critical message
创建了自定义的 Logger 对象,就不要在用 logging 中的日志输出方法了,这些方法使用的是默认配置的 Logger 对象,否则会输出的日志信息会重复
从字典中获取配置信息:
import logging.configconfig = {'version': 1,'formatters': {'simple': {'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',},# 其他的 formatter},'handlers': { #定义处理器,用来创建 Handler 对象,不能和 filename 、stream 参数一起使用,否则也会抛出 ValueError 异常'console': { 'class': 'logging.StreamHandler','level': 'DEBUG','formatter': 'simple'},'file': {'class': 'logging.FileHandler','filename': 'logging.log','level': 'DEBUG','formatter': 'simple'},# 其他的 handler},'loggers':{'StreamLogger': {'handlers': ['console'],'level': 'DEBUG',},'FileLogger': {# 既有 console Handler,还有 file Handler'handlers': ['console', 'file'],'level': 'DEBUG',},# 其他的 Logger}
}logging.config.dictConfig(config)
StreamLogger = logging.getLogger("StreamLogger")
FileLogger = logging.getLogger("FileLogger")
# 省略日志输出
从配置文件中获取配置信息:
init格式:
[对象]
键=值1,值2
[loggers]
keys=root,sampleLogger[handlers]
keys=consoleHandler[formatters]
keys=sampleFormatter[logger_root]
level=DEBUG
handlers=consoleHandler[logger_sampleLogger]
level=DEBUG
handlers=consoleHandler
qualname=sampleLogger
propagate=0[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=sampleFormatter
args=(sys.stdout,)[formatter_sampleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
testinit.py 文件
import logging.configlogging.config.fileConfig(fname='test.ini', disable_existing_loggers=False)
logger = logging.getLogger("sampleLogger")
# 省略日志输出