目录
前言
在项目中我们用到logging模块的地方非常之多,一个好的日志格式可以为我们的后期排查bug的工作带来很多方便,所以logging能使用好是非常重要的。
这篇文章中,主要讲一个比较好的logging日志的使用模式。在简单介绍logging的几个函数后,我会把这个模式的代码贴出来,供大家参考。这个模式也是我在项目中看到别人这样写,觉得不错,摘抄下来的。
一、logging模块的用法
logging模块的用法,一搜一大堆介绍,并且也比较简单,因此这里只是简单的说说。
1、使用步骤
配置日志信息 logging.basicConfig
取得 logging.Logger 对象
使用 Logger 对象输出信息
1.1 logging.basicConfig()
我们在使用logging时,首先要配置怎么去采集日志,这个配置给了我们非常大的自由度,用来自定义log的打印方式,下面就介绍一下,因为 logging.basicConfig真的非常重要。
1.1.1 默认配置
如果我们不使用logging.basicConfig()配置打印格式,那么也会有个默认的日志格式。如下:
BASIC_FORMAT(%(levelname)s:%(name)s:%(message)s)
我们可以看下面代码的例子
import logging
logging.basicConfig(
level=logging.DEBUG,
)
logger = logging.getLogger()
logger.debug("This is test message")
在ID E中输出
1.2 logging.basicConfig()的参数详解
logging.basicConfig()可以接受如下的参数,
filename: 指定日志文件名, 此时不会再输出到 StreamHandler 中, 即使指定了新的 stream
filemode: 指定日志文件的打开模式, 'w'或者'a', 默认为'a'
format: 指定输出的内容格式, 其配置信息见下文
datefmt: 输出日期和时间的格式字符串. 与 time.strftime 格式兼容, 不能指定到毫秒级别, 其详细信息见下文
level 设置日志输出的级别, 小于此级别的信息将被忽略, 默认为 WARNING
stream 指定输出的流, 默认为 sys.stderr, 如果指定了 filename, 此参数不起作用
handlers (不介绍)
force (不介绍)
1.2.1 level
日志级别:这个不用过多介绍,大家应该都知道
级别 值 描述
CRITICAL/FATAL 50 关键错误消息
ERROR 40 错误
WARNING(WARN) 30 警告消息
INFO 20 通知消息
DEBUG 10 调试
NOTSET 0 无级别
1.2.2 format(很重要)
自动义打印格式,完全就靠这个format
format 配置格式:
%(name)s logger 名称, 即调用 logging.getLogger 函数传入的参数
%(levelno)s 数字形式的日志记录级别
%(levelname)s 日志级别文本描述, 即"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"
%(pathname)s 执行日志记录调用的源文件路径
%(filename)s 执行日志记录调用的源文件名
%(module)s 执行日志记录调用的模块名称
%(lineno)d 执行日志记录调用的行号
%(funcName)s 执行日志记录调用的函数路径
%(created)s 执行日志记录调用的时间, 它是 time.time() 返回的数字
%(asctime)s 执行日志记录调用的ascii格式的时间, 其格式由 datefmt 指定
%(msecs)d 执行日志记录调用的时间中的毫秒部分
%(thread)d 线程id (if available)
%(threadName)s 线程名称 (if available)
%(process)d 进程ID (if available)
%(message)s 记录的消息, 如 logging.getLogger().debug(msg) 指定的 msg
1.2.3 datefmt(它有很多参数,这里只写一些,定制时间格式时可以用到,但是很少用,默认的格式就很友好)
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%M 分钟数(00=59)
%S 秒(00-59)
1.2.4 filename
这个字段指定日志打印到的文件,如果不设置,就会直接输出到屏幕上。
2、logging.getLogger()
获取一个logger,logger的一个重要属性就是他的name。每个logger遍布在各个模块中采集日志。我们在basicConfig中的format参数中若使了 %(name)s 就可以取到当前的logger的name,用于区分到底是哪个文件/模块 的日志。
3、使用logger对象输出消息
logger = logging.getLogger(__name__)
logger.debug("This is test message")
可以选择debug、warnning、error等等级。
二、工程中一个log打印模板
import logging
import os
def init():
global root, app_log
level_default = os.getenv("logging_level_default", logging.DEBUG)
level_asyncio = os.getenv("logging_level_asyncio", logging.DEBUG)
level_websocket = os.getenv("logging_level_websocket", logging.WARNING)
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s %(levelname)s %(name)s %(processName)s.%(threadName)s[%(process)d.%(thread)d]:%(message)s",
)
logger = logging.getLogger()
root = get()
app_log = get("app")
get("asyncio").setLevel(level_asyncio)
get("websocket.protocol").setLevel(level_websocket)
def get(name=None):
return logging.getLogger(name)