Python logging 日志模块

1、logging 模块的日志级别

  • DEBUG:数值表示:10,最详细的日志信息,典型应用场景是 问题诊断
  • INFO:数值表示:20,信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作
  • WARNING:数值表示:30,当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的
  • ERROR:数值表示:40,由于一个更严重的问题导致某些功能不能正常运行时记录的信息
  • CRITICAL:数值表示:50,当发生严重错误,导致应用程序不能继续运行时记录的信息

 2、logging 模块定义的模块级别的常用函数

  • logging.debug(msg, *args, **kwargs) -- 创建一条严重级别为DEBUG的日志记录
  • logging.info(msg, *args, **kwargs) -- 创建一条严重级别为INFO的日志记录
  • logging.warning(msg, *args, **kwargs) -- 创建一条严重级别为WARNING的日志记录
  • logging.error(msg, *args, **kwargs) -- 创建一条严重级别为ERROR的日志记录
  • logging.critical(msg, *args, **kwargs) -- 创建一条严重级别为CRITICAL的日志记录
  • logging.log(level, *args, **kwargs) -- 创建一条严重级别为level的日志记录
  • logging.basicConfig(**kwargs) -- 对root logger进行一次性配置
import logging

logging.debug("debug_msg")
logging.info("info_msg")
logging.warning("warning_msg")
logging.error("error_msg")
logging.critical("critical_msg")

#输出结果如下:
2020-03-02 14:27:13,304 WARNING warning_msg
2020-03-02 14:27:13,304 ERROR error_msg
2020-03-02 14:27:13,304 CRITICAL critical_msg

# 默认情况下 Python 的 logging 模块将日志打印到了标准输出中,且只显示了大于等于 WARNING 级别的日志,这说明默认的日志级别设置为 WARNING(日志级别等级 CRITICAL > ERROR > WARNING > INFO > DEBUG)

3、logging.basicConfig() 函数配置日志参数说明

参数名称       描述
filename 指定日志输出目标文件的文件名(可以写文件名也可以写文件的完整的绝对路径,写文件名日志放执行文件目录下,写完整路径按照完整路径生成日志文件),指定该设置项后日志信心就不会被输出到控制台了
filemode 指定日志文件的打开模式,默认为'a'。需要注意的是,该选项要在filename指定时才有效
format 指定日志格式字符串,即指定日志输出时所包含的字段信息以及它们的顺序。logging模块定义的格式字段下面会列出。
datefmt 指定日期/时间格式。需要注意的是,该选项要在format中包含时间字段%(asctime)s时才有效
level 指定日志器的日志级别
stream 指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream。需要说明的是,stream和filename不能同时提供,否则会引发 ValueError异常
style Python 3.2中新添加的配置项。指定format格式字符串的风格,可取值为'%'、'{'和'$',默认为'%'
handlers Python 3.3中新添加的配置项。该选项如果被指定,它应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger。需要说明的是:filename、stream和handlers这三个配置项只能有一个存在,不能同时出现2个或3个,否则会引发ValueError异常。

4、logging.basicConfig() 参数中 format 属性变量解释

字段/属性名称使用格式描述
asctime %(asctime)s 将日志的时间构造成可读的形式,默认情况下是‘2016-02-08 12:00:00,123’精确到毫秒
name %(name)s 所使用的日志器名称,默认是'root',因为默认使用的是 rootLogger
filename %(filename)s 调用日志输出函数的模块的文件名; pathname的文件名部分,包含文件后缀
funcName %(funcName)s 由哪个function发出的log, 调用日志输出函数的函数名
levelname %(levelname)s 日志的最终等级(被filter修改后的)
message %(message)s 日志信息, 日志记录的文本内容
lineno %(lineno)d 当前日志的行号, 调用日志输出函数的语句所在的代码行
levelno %(levelno)s 该日志记录的数字形式的日志级别(10, 20, 30, 40, 50)
pathname %(pathname)s 完整路径 ,调用日志输出函数的模块的完整路径名,可能没有
process %(process)s 当前进程, 进程ID。可能没有
processName %(processName)s 进程名称,Python 3.1新增
thread %(thread)s 当前线程, 线程ID。可能没有
threadName %(thread)s 线程名称
module %(module)s 调用日志输出函数的模块名, filename的名称部分,不包含后缀即不包含文件后缀的文件名
created %(created)f 当前时间,用UNIX标准的表示时间的浮点数表示; 日志事件发生的时间--时间戳,就是当时调用time.time()函数返回的值
relativeCreated %(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数; 日志事件发生的时间相对于logging模块加载时间的相对毫秒数
msecs %(msecs)d 日志事件发生事件的毫秒部分。logging.basicConfig()中用了参数datefmt,将会去掉asctime中产生的毫秒部分,可以用这个加上
import logging

# #这里可以用 logging.basicConfig() 函数调整日志级别、输出格式和输出内容等
logging.basicConfig(level = logging.DEBUG,
                    format = "%(asctime)s %(pathname)s %(funcName)s [line:%(lineno)d] %(levelname)s %(message)s",
                    datefmt = "%Y-%m-%d %H:%M:%S",
                    filename="error.log",
                    filemode="w")

logging.debug("debug_msg")
logging.info("info_msg")
logging.warning("warning_msg")
logging.error("error_msg")
logging.critical("critical_msg")

# 日志输出结果如下
2022-11-02 15:47:54 D:/Evan_duoceshi/my_code_file/practice/logging_module.py <module> [line:12] DEBUG debug_msg
2022-11-02 15:47:54 D:/Evan_duoceshi/my_code_file/practice/logging_module.py <module> [line:13] INFO info_msg
2022-11-02 15:47:54 D:/Evan_duoceshi/my_code_file/practice/logging_module.py <module> [line:14] WARNING warning_msg
2022-11-02 15:47:54 D:/Evan_duoceshi/my_code_file/practice/logging_module.py <module> [line:15] ERROR error_msg
2022-11-02 15:47:54 D:/Evan_duoceshi/my_code_file/practice/logging_module.py <module> [line:16] CRITICAL critical_msg

5、logging 模块的处理流程

  • 四大组件
    • 日志器 (Logger):产生日志的一个接口。  
    • 处理器 (Handler):把产生的日志发送到相应的目的地。  
    • 过滤器 (Filter):更精细的控制那些日志输出。  
    • 格式器 (Formatter):对输出的信息进行格式化。  
  • Logger
    • 操作 Logger.setLevel()  # 设置日志器将会处理的日志消息的最低严重级别  
    • Logger.addHandler()  
    • Logger.moveHander()   # 上面两个函数,为该 logger 对象添加和移除一个 handler 对象  
    • Logger.addFilter()  
    • Logger.removeFilter()   # 上面两个函数,为该 logger 对象添加和移除一个 filter 对象  
    • Logger.debug  # 产生一条 debug 级别的日志,同理,info,error 的日志消息  
    • Logger.exception   # 创建一个类似于 Logger.error 的日志消息,但是 exception 可以将报错信息一起打印到日志中,error 级别日志只会把定义的错误信息打印出来,不会记录系统报错信息
    • Logger.log()   # 获取一个明确的日志 level 参数类型创建一个日志记录  
  • 如何得到一个logger对象
    • 实例化:logging.getLogger()  
  • Handler
    • 把 log 发送到指定位置  
    • 方法
      • setLevel\setFormat\addFilter\removeFilter    
    • 不需要直接使用,Handler 是基类 logging.StreamHandler   # 将日志消息发送到输出到 Stream。如 std.out,std.err 或任何 file-like 对象 
      • logging.FileHandler   # 将日志消息发送到磁盘文件。默认情况下文件大小会无限增长    
      • logging.handlers.RotatongFileHandler   # 将日志消息发送到磁盘文件,并支持日志文件按大小切割    
      • logging.handlers.TimeRotatingFileHandler   # 将日志消息发送到磁盘文件,并支持日志文件按时间切割    
      • logging.handlers.HTTPHandler   # 将日志消息以 GET 或 POST 的方式发送到一个指定 email 地址    
      • logging.NullHandler   # 该 Handler 实例会忽略 error message 通常想被想使用 logging 的 library    

6、logging.getLogger() 输出日志到文件和屏幕

import logging
"""
我创建了一个格式器formatter,两个处理器fh和ch。
将格式器绑定到处理器上,然后将处理器绑定到logger对象,接下来我们对logger操作即可。
记录的一条日志既输出到屏幕上也输出到文件内
"""
# 获取logger对象,用于记录日志
logger = logging.getLogger()
# 创建一个handler,用于写入日志,输出到文件
fh = logging.FileHandler("error.log")
# 创建一个handler,用于输出到屏幕
ch = logging.StreamHandler()
# 创建一个formatter,用于处理日志格式
formatter = logging.Formatter("%(asctime)s %(pathname)s %(funcName)s [line:%(lineno)d] %(levelname)s %(message)s")
# 绑定formatter 到handler上
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 设置一个日志记录级别
logger.setLevel(logging.DEBUG)
# 绑定handler到logger对象上
logger.addHandler(fh)
logger.addHandler(ch)
# 定义好函数,我们直接调用就可以了
# 记录一条日志
logger.debug("This is a debug")
# 封装日志装饰器记录函数运行日志
import logging

def log(filename):
    def set_log(func):
        def ouputLog(*args, **kwargs):
            # 获取logger对象,用于记录日志
            logger = logging.getLogger()
            # 创建一个handler,用于写入日志,输出到文件
            fh = logging.FileHandler(filename)
            # 创建一个handler,用于输出到屏幕
            ch = logging.StreamHandler()
            # 创建一个formatter,用于处理日志格式
            formatter = logging.Formatter("%(asctime)s %(pathname)s [%(funcName)s方法] [line:%(lineno)d] %(levelname)s %(message)s")
            # 绑定formatter 到handler上
            fh.setFormatter(formatter)
            ch.setFormatter(formatter)
            # 设置日志记录级别
            logger.setLevel(logging.DEBUG)
            # 绑定handler到logger对象上
            logger.addHandler(fh)
            logger.addHandler(ch)
            func(*args, **kwargs)
        return ouputLog
    return set_log

@log("error2.log")
def add(num1, num2):
    logging.info("当前传进来的参数有 {} 和 {}".format(num1, num2))
    res = num1 + num2
    logging.info("相加结果等于:{}".format(res))
    return res

add(10, 20)

# 结果如下:
2022-11-02 16:54:26,235 D:/Evan_duoceshi/my_code_file/practice/logging_module.py [add方法] [line:75] INFO 当前传进来的参数有 10 和 20
2022-11-02 16:54:26,235 D:/Evan_duoceshi/my_code_file/practice/logging_module.py [add方法] [line:77] INFO 相加结果等于:30

 

posted @ 2020-03-02 14:34  Evan0813  阅读(337)  评论(0)    收藏  举报