1 logging 日志级别
级别 | 级别数量 | 使用场合 |
---|---|---|
DEBUG | 10 | 详细信息,常用语调试 |
INFO | 20 | 程序正常运行过程中产生的一些信息 |
WARNING | 20 | 警告用户,虽然程序还在正常工作,但有可能发生错误 |
ERROR | 40 | 由于更严重的问题,程序已不能执行一些功能了 |
CRITICAL | 50 | 严重错误,程序已不能继续运行了 |
2 logging 默认的是warning级别
import logging
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")
执行结果如下:
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
3 可以通过logging.basicConfig(level=logging.DEBUG) 来设置日志级别
import logging
logging.basicConfig(level=logging.DEBUG)
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")
运行结果如下:
DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
4 logging日志是一部写入的,logging打印的内容和print打印的内筒先后顺序是不一致的
import logging
print("this is print log")
logging.basicConfig(level=logging.DEBUG)
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")
运行结果有可能是下面这种输出顺序
DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
this is print log
5 logging.basicConfig(filename=“demo.log”)可以指定日志文件名,默认在当前目录下生成文件,此时不再往屏幕打印日志,而是将日志信息输出到指定的日志文件中去
import logging
print("this is print log")
logging.basicConfig(filename="demo.log",level=logging.DEBUG)
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")
运行后屏幕上输出结果为:
this is print log
而在当前文件下生成了一个demo.log的日志文件,此日志文件的内容为:
DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
6 logging.basicConfig(filemode=‘w’) 可以指定日志文件的模式,w表示每次清空日志文件,重新写入,a表示在日志文件后面追加,默认的模式为a
将上述 5 中的实例代码再执行一次,demo.log中内容为:
DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
若代码修改为如下,再执行:
import logging
print("this is print log")
logging.basicConfig(filename="demo.log",filemode='w',level=logging.DEBUG)
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")
运行后,demo.log中的内容又恢复到如下内容:
DEBUG:root:this is debug log
INFO:root:this is info log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
7 logging 向日志中写入变量的方式
import logging
logging.basicConfig(level=logging.DEBUG)
name="zhangsan"
age=20
logging.debug("name: %s age: %d",name,age)
logging.info("name: %s age: %d" %(name,age))
logging.warning("name: {} age: {}".format(name,age))
logging.error("name: {name} age: {age}".format(name=name,age=age))
运行结果如下:
DEBUG:root:name: zhangsan age: 20
INFO:root:name: zhangsan age: 20
WARNING:root:name: zhangsan age: 20
ERROR:root:name: zhangsan age: 20
8 日志内容格式增加一些公共的内容
import logging
logging.basicConfig(format=("%(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(message)s"),
datefmt="%Y-%m-%d_%H:%M:%S",
level=logging.DEBUG)
name="zhangsan"
age=20
logging.debug("name: %s age: %d",name,age)
logging.info("name: %s age: %d" %(name,age))
logging.warning("name: {} age: {}".format(name,age))
logging.error("name: {name} age: {age}".format(name=name,age=age))
运行结果为:
2020-08-03_07:20:42 | DEBUG | test1.py:9 | name: zhangsan age: 20
2020-08-03_07:20:42 | INFO | test1.py:10 | name: zhangsan age: 20
2020-08-03_07:20:42 | WARNING | test1.py:11 | name: zhangsan age: 20
2020-08-03_07:20:42 | ERROR | test1.py:12 | name: zhangsan age: 20
9 logging的高级应用
logging模块采用了模块化设计,主要包含四种组件
- Loggers:记录器,提供应用程序代码能直接使用的接口
- Handlers:处理器,将记录器产生的日志发送到目的地
- Filters:过滤器,提供更好的粒度控制,决定哪些日志会被输出
- 格式化器:设置内置内容的组成结构和消息字段
10 logging的高级应用流程
|---创建屏幕StreamHandler--设置日志等级---|
创建一个logger并设置默认等级---| |----创建formatter----用formatter渲染所有的hansdler----将所有的handler加入logger内----程序调用logger
|---创建文件FileHandler--设置日志等级-----|
11 loggers记录器
-
提供应用程序的调用接口
logger=logging。getLogger(name)
logger是单例的 -
决定日志记录的级别
logger.setLevel()
-
将日志内容传递到相关联的handlers中
logger.addHandler()
logger。removeHandler()
12 handler处理器
-
StreamHandler
标准输出stdout(如显示器)分发器
创建方法: sh=logging.StreamHandler(stream=None)
-
FileHandler
将日志保存到磁盘文件的处理器
创建方法:fh=logging.FileHandler(filename,mode=“a”,enconding=None,delay=False)
-
setFormatter(): 设置当前handler对象使用的消息格斯
13 常用的Handlers处理器
- StreamHandler
- FileHandler
- BaseRotatingHandler
- RotatingHandler
- TimedRotatingFileHandler
- SocketHandler
- DatagramHandler
- SMTPHandler
- SysLogHandler
- NTEventLogHandler
- HTTPHandler
- WatchedFileHandler
- QueueHandler
- NullHandler
14 常见的formatter格式
属性 | 格式 | 描述 |
---|---|---|
asctime | %(asctime)s | 日志产生的时间,默认格式为2020-08-03 12.12.12,265 |
created | %(created)f | time.time()生成的日志创建时间戳 |
filename | %(filename)s | 生成日志的程序名 |
funcName | %(funcName)s | 调用日志的函数名 |
levelname | %(levelname)s | 日志级别(DEBUG,INFO,WARNING,ERROR,CRITICAL) |
levelno | %(levelno)s | 日志级别对应的数值 |
lineno | %(lineno)s) | 日志所针对的代码行号(如果可用的话) |
module | %(module)s | 生成日志的模块名 |
mesecs | %(mesecs)d | 日志生成的时间的毫秒部分 |
message | %(message)s | 具体的日志信息 |
name | %(name)s | 日志调用者 |
pathname | %(pathname)s | 生成日志的文件的完整路径 |
process | %(process)d | 生成日志的进程id(如果可用) |
processName | %(processName)s | 进程名(如果可用) |
thread | %(thread)d | 生成日志的线程id(如果可用) |
threadName | %(threadName)s | 线程名(如果可用) |
15 下面两段代码的功能是完全一样的,使用logging直接调info、debug等日志与实例化一个默认的root logger是一样的,换言之,使用logging直接调日志方法的方式就是通过获取root日志来实现的
import logging
logging.debug("this is debug log")
logging.info("this is info log")
logging.warning("this is warning log")
logging.error("this is error log")
logging.critical("this is critical log")
logger=logging.getLogger()
logger.debug("this is debug log")
logger.info("this is info log")
logger.warning("this is warning log")
logger.error("this is error log")
logger.critical("this is critical log"
运行结果如下:
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
WARNING:root:this is warning log
ERROR:root:this is error log
CRITICAL:root:this is critical log
16 下面一段代码使用getLogger时指定一个名称,即实例化一个logger,然后设置两种处理器,分别往控制台和文件中写日志,还可以设置日志内容的格式,具体如下所示
import logging
logger=logging.getLogger("test")
console_handler=logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
file_handler=logging.FileHandler(filename="demo.log")
file_handler.setLevel(logging.DEBUG)
formatter=logging.Formatter(fmt="%(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(message)s")
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
logger.addHandler(console_handler)
logger.addHandler(file_handler)
log=logger
log.debug("this is debug log")
("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")
运行结果如下:
2020-08-04 23:08:56,625 | WARNING | test1.py:25 | this is warning log
2020-08-04 23:08:56,625 | ERROR | test1.py:26 | this is error log
2020-08-04 23:08:56,625 | CRITICAL | test1.py:27 | this is critical log
并且在demo.log日志文件中写入了如下内容:
2020-08-04 23:08:56,625 | WARNING | test1.py:25 | this is warning log
2020-08-04 23:08:56,625 | ERROR | test1.py:26 | this is error log
2020-08-04 23:08:56,625 | CRITICAL | test1.py:27 | this is critical log
17 上述 16 的日志打印明显与本来的期望是不一致的,本来期望控制台和文件都是设置了DEBUG级别,但实际上控制台和文件中都打印了Warning的级别的日志
这里需要注意的是,logger默认的日志级别是warning,而日志的最终级别将取决于logger和handler级别的最高级别,所以上述16中虽然控制台和文件handler的日志级别都设置了debug,但是因为logger默认级别是warning,所以最终打印的都是warning级别,下面一段代码将logger设置为debug级别,然后将控制台设置为info,将文件handler设置为warning,然后再看一下效果:
import logging
logger=logging.getLogger("test")
logger.setLevel(logging.DEBUG)
console_handler=logging.StreamHandler()
console_handler.setLevel(logging.INFO)
file_handler=logging.FileHandler(filename="demo.log")
file_handler.setLevel(logging.WARNING)
formatter=logging.Formatter(fmt="%(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(message)s")
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
logger.addHandler(console_handler)
logger.addHandler(file_handler)
log=logger
log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")
运行结果如下:
2020-08-04 23:21:37,888 | INFO | test1.py:25 | this is info log
2020-08-04 23:21:37,888 | WARNING | test1.py:26 | this is warning log
2020-08-04 23:21:37,888 | ERROR | test1.py:27 | this is error log
2020-08-04 23:21:37,888 | CRITICAL | test1.py:28 | this is critical log
而在demo.log日志文件中写入了如下内容,此时与上述分析一致了
2020-08-04 23:21:37,888 | WARNING | test1.py:26 | this is warning log
2020-08-04 23:21:37,888 | ERROR | test1.py:27 | this is error log
2020-08-04 23:21:37,888 | CRITICAL | test1.py:28 | this is critical log
18 定义filter并给控制台的handler加一个filter,过滤的name与日志名称不一致,如下代码,此时则不会往控制台写日志,但日志文件的日志还是正常写的
import logging
logger=logging.getLogger("test")
logger.setLevel(logging.DEBUG)
console_handler=logging.StreamHandler()
console_handler.setLevel(logging.INFO)
file_handler=logging.FileHandler(filename="demo.log")
file_handler.setLevel(logging.WARNING)
formatter=logging.Formatter(fmt="%(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(message)s")
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
logger.addHandler(console_handler)
logger.addHandler(file_handler)
filter=logging.Filter("test1")
console_handler.addFilter(filter)
log=logger
log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")
此时运行后控制台结果为空,日志文件如下日志打印正常
2020-08-04 23:31:00,459 | WARNING | test1.py:29 | this is warning log
2020-08-04 23:31:00,459 | ERROR | test1.py:30 | this is error log
2020-08-04 23:31:00,459 | CRITICAL | test1.py:31 | this is critical log
19 配置文件的方式
- (1) 首先编写类似如下的log配置文件:logging.conf, 这里面定义了root和test两个logger
[loggers]
keys=root,test
[handlers]
keys=fileHandler,consoleHandler
[formatters];
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_test]
level=DEBUG
handlers=fileHandler,consoleHandler
qualname=test
propagate=0
[handler_consoleHandler]
class=StreamHandler
args=(sys.stdout,)
level=DEBUG
formatter=simpleFormatter
[handler_fileHandler]
class=handlers.TimedRotatingFileHandler
args=("test.log","midnight",1,0)
level=DEBUG
formatter=simpleFormatter
[formatter_simpleFormatter]
format=%(asctime)s|%(levelname)s|%(filename)s[line:%(lineno)d]|%(message)s
datafmt=%Y-%m-%d_%H:%M:%S
- (2)然后在py文件中编写如下代码,这里演示了root的logger和test的logger两种的使用方式
import logging.config
logging.config.fileConfig("logging.conf")
logger=logging.getLogger("test")
log=logger
log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")
rlog=logging.getLogger("root")
rlog.debug("this is debug log")
rlog.info("this is info log")
rlog.warning("this is warning log")
rlog.error("this is error log")
rlog.critical("this is critical log")
运行结果如下:
2020-08-05 00:25:02,673|DEBUG|test1.py[line:8]|this is debug log
2020-08-05 00:25:02,674|INFO|test1.py[line:9]|this is info log
2020-08-05 00:25:02,674|WARNING|test1.py[line:10]|this is warning log
2020-08-05 00:25:02,674|ERROR|test1.py[line:11]|this is error log
2020-08-05 00:25:02,674|CRITICAL|test1.py[line:12]|this is critical log
2020-08-05 00:25:02,674|DEBUG|test1.py[line:15]|this is debug log
2020-08-05 00:25:02,674|INFO|test1.py[line:16]|this is info log
2020-08-05 00:25:02,674|WARNING|test1.py[line:17]|this is warning log
2020-08-05 00:25:02,674|ERROR|test1.py[line:18]|this is error log
2020-08-05 00:25:02,674|CRITICAL|test1.py[line:19]|this is critical log
同时在test.log日志文件中生成如下日志:
2020-08-05 00:25:02,673|DEBUG|test1.py[line:8]|this is debug log
2020-08-05 00:25:02,674|INFO|test1.py[line:9]|this is info log
2020-08-05 00:25:02,674|WARNING|test1.py[line:10]|this is warning log
2020-08-05 00:25:02,674|ERROR|test1.py[line:11]|this is error log
2020-08-05 00:25:02,674|CRITICAL|test1.py[line:12]|this is critical log
20 在上述19的基础上,加入在其他文件中想使用建好的log系统进行日志的打印,有如下两种使用方法:
import test1
import logging
log=logging.getLogger("test")
log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")
log=test1.logger
log.debug("this is debug log")
log.info("this is info log")
log.warning("this is warning log")
log.error("this is error log")
log.critical("this is critical log")
运行结果如下:
2020-08-05_00:31:35|DEBUG|test2.py[line:8]|this is debug log
2020-08-05_00:31:35|INFO|test2.py[line:9]|this is info log
2020-08-05_00:31:35|WARNING|test2.py[line:10]|this is warning log
2020-08-05_00:31:35|ERROR|test2.py[line:11]|this is error log
2020-08-05_00:31:35|CRITICAL|test2.py[line:12]|this is critical log
2020-08-05_00:31:35|DEBUG|test2.py[line:16]|this is debug log
2020-08-05_00:31:35|INFO|test2.py[line:17]|this is info log
2020-08-05_00:31:35|WARNING|test2.py[line:18]|this is warning log
2020-08-05_00:31:35|ERROR|test2.py[line:19]|this is error log
2020-08-05_00:31:35|CRITICAL|test2.py[line:20]|this is critical log
日志文件中也生成了对应的日志:
2020-08-05_00:31:35|DEBUG|test2.py[line:8]|this is debug log
2020-08-05_00:31:35|INFO|test2.py[line:9]|this is info log
2020-08-05_00:31:35|WARNING|test2.py[line:10]|this is warning log
2020-08-05_00:31:35|ERROR|test2.py[line:11]|this is error log
2020-08-05_00:31:35|CRITICAL|test2.py[line:12]|this is critical log
2020-08-05_00:31:35|DEBUG|test2.py[line:16]|this is debug log
2020-08-05_00:31:35|INFO|test2.py[line:17]|this is info log
2020-08-05_00:31:35|WARNING|test2.py[line:18]|this is warning log
2020-08-05_00:31:35|ERROR|test2.py[line:19]|this is error log
2020-08-05_00:31:35|CRITICAL|test2.py[line:20]|this is critical log
21 在try - except语句块中,打印异常日志可以使用log.exception(e),这个函数可以将程序错误调用栈打印出来
import logging.config
logging.config.fileConfig("logging.conf")
logger=logging.getLogger("test")
log=logger
try:
a=1/0
except Exception as e:
log.exception(e)
运行结果如下:
2020-08-05_00:35:14|ERROR|test1.py[line:12]|division by zero
Traceback (most recent call last):
File "G:/lamb_source/test/log/test1.py", line 10, in <module>
a=1/0
ZeroDivisionError: division by zero