前言:python自带有一个logging标准模块,不需要另外安装,可以直接import使用,主要用于输出测试过程内部执行情况、错误、异常等信息,可以设置输出日志的等级、日志保存路径等。
目录
先做个简单的实验,导入logging模块,输入以下代码然后查看输出:
import logging
logging.critical('logging critical message.')
logging.error('logging error message')
logging.warning('logging warning message')
logging.info('logging info message')
logging.debug('logging debug message')
输出结果如下:
CRITICAL:root:logging critical message.
ERROR:root:logging error message
WARNING:root:logging warning message
通过输出结果再去理解logging模块:
python提供的logging模块一共分了5个级别,由低到高分别是debug、info、warning、error、critical,在不设置输出级别的时候默认只会打印warning级别及其以上的日志信息。
各级别说明如下:
Level | Numeric value | Comments |
---|---|---|
DEBUG | 10 | 调试过程中使用DEBUG等级,如算法中每个循环的中间状态 |
INFO | 20 | 处理请求或者状态变化等日常事务 |
WARNING | 30 | 发生很重要的事件,但是并不是错误时,如用户登录密码错误 |
ERROR | 40 | 发生错误时,如IO操作失败或者连接问题 |
CRITICAL | 50 | 特别糟糕的事情,如内存耗尽、磁盘空间为空,一般很少使用 |
如果想要控制log级别的输出,我们只需要在前面加logging.basicConfig(level=logging.级别)即可,设置好之后就会输出设置级别及其以上的日志信息,注意级别是大写,如下:
import logging
logging.basicConfig(level=logging.ERROR)
logging.critical('logging critical message.')
logging.error('logging error message')
logging.warning('logging warning message')
logging.info('logging info message')
logging.debug('logging debug message')
# 输出结果
CRITICAL:root:logging critical message.
ERROR:root:logging error message
basicConfig中还能指定输出格式,添加日志时间,日志文件存储路径,以及写入模式,基本格式如下:
import logging
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='[%Y-%m_%d %H:%M:%S]',
filename='./my.log',
filemode='a')
logging.critical('logging critical message.')
logging.error('logging error message')
logging.warning('logging warning message')
logging.info('logging info message')
logging.debug('logging debug message')
在同目录下会生成一个my.log的日志文件,内容如下:
[2022-03_14 22:17:01] log_demo1.py[line:8] CRITICAL logging critical message.
[2022-03_14 22:17:01] log_demo1.py[line:9] ERROR logging error message
[2022-03_14 22:17:01] log_demo1.py[line:10] WARNING logging warning message
[2022-03_14 22:17:01] log_demo1.py[line:11] INFO logging info message
设置logging,创建一个FileHandler,并对输出消息的格式进行设置,将其添加到logger,然后将日志写入到指定的文件中,格式如下:
import logging
# 初始化Logger对象
logger = logging.getLogger(__name__) # 获取main函数
logger.setLevel(level=logging.INFO) # 设置级别
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 格式控制
# 初始化文件对象
handler = logging.FileHandler("demo.log") # 定义handler代表文件,选择FileHandler
handler.setFormatter(formatter)
# 把文件对象添加到日志Handler中
logger.addHandler(handler)
# 输出日志信息在文件中
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")
在同一目录下会生成一个demo.log的文件,内容如下:
2022-03-14 23:01:23,430 - __main__ - INFO - Start print log
2022-03-14 23:01:23,430 - __main__ - WARNING - Something maybe fail.
2022-03-14 23:01:23,430 - __main__ - INFO - Finish
有些时候不想去打开文件,想要在控制台直接查看日志,那就需要额外做一些代码设置,
logger中添加StreamHandler初始化控制台对象,基本格式如下:
import logging
# 初始化Logger对象
logger = logging.getLogger(__name__) # 获取main函数
logger.setLevel(level=logging.INFO) # 设置级别
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 格式控制
# 初始化控制台对象
console = logging.StreamHandler() # 定义console代表控制台,选择StreamHandler
console.setFormatter(formatter)
# 把控制台对象添加到日志Handler中
logger.addHandler(console)
# 输出日志信息在控制台
logger.info("Start print log")
logger.debug("Do something")
logger.warning("Something maybe fail.")
logger.info("Finish")
控制台输出结果如下:
2022-03-14 22:26:48,337 - __main__ - INFO - Start print log
2022-03-14 22:26:48,337 - __main__ - WARNING - Something maybe fail.
2022-03-14 22:26:48,337 - __main__ - INFO - Finish
在框架中,如果多个文件都需要输出日志,那最好是将日志的初始化过程封装到一个文件中,然后其他文件直接调用即可。
我们可以创建一个公共的py文件,将我们的初始化操作放进去,正常我们任选日志输出或者控制台输出即可,不需要两者都设置的,这边的话将两者放在一起方便讲解:
注意:初始化日志对象的名字“mainModule”可以随便起,但其他文件引用的时候一定要对应加上sub后缀“mainModule.sub”
# 公共配置文件public_log.py
# **********************************
# 公共日志模块设置
# **********************************
import logging
# 初始化日志对象
logger = logging.getLogger('mainModule') # 名字可以随便取
logger.setLevel(level=logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 初始化日志文件对象
handler = logging.FileHandler('log1.log')
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
# 初始化控制台对象
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
console.setFormatter(formatter)
# 添加日志文件和控制台对象
logger.addHandler(handler)
logger.addHandler(console)
这样当我们在其他文件中想要使用日志的时候,直接引用该文件即可,当然还是需要给当前文件做一个初始化的操作:
# 同目录下另一个.py文件
import logging
from test_log_demo import public_log
# 初始化日志对象
logger = logging.getLogger('mainModule.sub') # 注意一定要公共文件里的名字加上‘.sub’
# 日志信息
logger.info("this is another module using logging")
logger.warning('另一个模块打印的警告')
按照公共日志模块的设置,我们可以在同目录下找到一个log1.log的文件,同时控制台的输出如下:
2022-03-16 00:37:56,470 - mainModule.sub - INFO - this is another module using logging
2022-03-16 00:37:56,470 - mainModule.sub - WARNING - 另一个模块打印的警告
关于日志模块,python也提供了一种对应的公共配置文件方法,后缀名必须是.conf文件格式。
创建一个.conf文件,下面模板可直接复制使用。
模板如下:
注意,下面模板复制到.conf中后,记得把注释删掉,因为不是.py文件所以后面引用的时候会报中文错误。
# 创建log.cong文件
###############################################
[loggers]
keys=root # 名字可按自己喜好取
[logger_root]
level=DEBUG # 定义全局日志输出级别
handlers=hand01 # 定义输出到控制台对象
###############################################
[handlers]
keys=hand01 # 需要和上面的定义相一致
[handler_hand01]
class=StreamHandler # 指定控制台模式
level=WARNING # 定义控制台输出级别,是局部定义
formatter=form01
args=(sys.stderr,) # 启用控制台,名字固定不可更改,注意最后还有一个逗号
###############################################
[formatters]
keys=form01,form02 # 可定义多种格式,按名字取用想要的格式
[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s
datefmt=%a, %d %b %Y %H:%M:%S
[formatter_form02]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt=%a, %d %b %Y %H:%M:%S
在其他文件中导入logging.config包之后,可直接引用,不需要在导入文件,参考如下:
import logging
import logging.config
logging.config.fileConfig("log.conf") # 对应conf文件名
logger = logging.getLogger("root") # 对应conf文件中key值
logger.debug('This is debug message')
logger.info('This is info message')
logger.warning('This is warning message')
输出如下,是按照控制台定义的输出级别来输出:
Wed, 16 Mar 2022 01:21:33 log_demo5.py[line:9] WARNING This is warning message
格式与上面略有不同,同样可直接复制模板。
分别定义了root,main两个对象,可分别对控制台与文件进行初始化。
注意:qualname=main 文件控制中这一项的值不可缺少,作用是在文件中只会输出由main定义的日志信息,而不会输出root定义的控制台信息,可以将控制台与日志割裂开来,在日志中只输出想要输出的日志。
基础模板如下:
# 创建了一个file_console.conf文件
[loggers]
keys=root,main
[handlers]
keys=consoleHandler,fileHandler
[formatters]
keys=fmt
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_main]
level=DEBUG
qualname=main
handlers=fileHandler
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=fmt
args=(sys.stdout,)
[handler_fileHandler]
class=logging.handlers.RotatingFileHandler
level=DEBUG
formatter=fmt
args=('test.log','a',20000,5,)
[formatter_fmt]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
其他文件想要引用的话,代码如下:
注意:文件名要对应,控制台与文件的初始化也要对应上面定义的key值。
import logging
import logging.config
logging.config.fileConfig('file_console.conf')
root_logger = logging.getLogger('root')
root_logger.debug('test root logger...')
main_logger = logging.getLogger('main')
main_logger.info('test main logger')
main_logger.info('test another')
控制台输出如下:
2022-03-16 01:40:11,677 - root - DEBUG - test root logger...
2022-03-16 01:40:11,677 - main - INFO - test main logger
2022-03-16 01:40:11,677 - main - INFO - test another
在同一目录下生成一个test.log文件,文件内容如下:
2022-03-16 01:40:11,677 - main - INFO - test main logger
2022-03-16 01:40:11,677 - main - INFO - test another
到此,我们的日志的基本设置便完成了。当然还有很多其他操作,怎奈所学有限,后续继续完善吧。