Python日志模块logging用法


Posted in Python onJune 05, 2022

一、概述

步骤

  • 创建logger对象
  • 创建handler对象
  • 创建formatter对象
  • 把formatter绑定到handler对象上
  • 把handler对象绑定到logger对象上
  • 设置级别
  • 测试

二、低配logging

日志总共分为以下五个级别,这个五个级别自下而上进行匹配 debug-->info-->warning-->error-->critical,默认最低级别为warning级别。

critical=50、error =40 、arning =30、info = 20、debug =10

v1:屏幕输出

v1版本无法指定日志的级别;无法指定日志的格式;只能往屏幕打印,无法写入文件。

import logging

logging.debug('调试信息')
logging.info('正常信息')
logging.warning('警告信息')  # WARNING:root:警告信息
logging.error('报错信息')  # ERROR:root:报错信息
logging.critical('严重错误信息')  # CRITICAL:root:严重错误信息

v2:输出到文件

v2版本不能指定字符编码;只能往文件中打印。

可在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:

  • filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
  • filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
  • format:指定handler使用的日志显示格式。
  • datefmt:指定日期时间格式。
  • level:设置rootlogger(后边会讲解具体概念)的日志级别
  • stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
import logging
# 日志的基本配置

logging.basicConfig(filename='access.log',
                    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    level=10)

logging.debug('调试信息')  #  2019-11-28 18:25:26 PM - root - DEBUG -run: 调试信息
logging.info('正常信息')  #  2019-11-28 18:25:26 PM - root - INFO -run: 正常信息
logging.warning('警告信息')  #  2019-11-28 18:25:26 PM - root - WARNING -run: 警告信息
logging.error('报错信息')  #  2019-11-28 18:25:26 PM - root - ERROR -run: 报错信息
logging.critical('严重错误信息')  #  2019-11-28 18:25:26 PM - root - CRITICAL -run: 严重错误信息

format参数中可能用到的格式化串:

  • %(name)s :Logger的名字
  • %(levelno)s :数字形式的日志级别
  • %(levelname)s :文本形式的日志级别
  • %(pathname)s 调:用日志输出函数的模块的完整路径名,可能没有
  • %(filename)s :调用日志输出函数的模块的文件名
  • %(module)s :调用日志输出函数的模块名
  • %(funcName)s :调用日志输出函数的函数名
  • %(lineno)d :调用日志输出函数的语句所在的代码行
  • %(created)f :当前时间,用UNIX标准的表示时间的浮 点数表示
  • %(relativeCreated)d :输出日志信息时的,自Logger创建以 来的毫秒数
  • %(asctime)s :字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
  • %(thread)d :线程ID。可能没有
  • %(threadName)s :线程名。可能没有
  • %(process)d :进程ID。可能没有
  • %(message)s:用户输出的消息

v3:使用内置各种对象

logging模块包含四种角色:logger、Filter、Formatter、Handler对象

  • logger:产生日志的对象
  • Filter:过滤日志的对象
  • Formatter:可以定制不同的日志格式对象,然后绑定给不同的Handler对象使用,以此来控制不同的Handler的日志格式
  • Handler:接收日志然后控制打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端
import logging

# 1、logger对象:负责产生日志,然后交给Filter过滤,然后交给不同的Handler输出
logger = logging.getLogger(__file__)

# 2、Filter对象:不常用,略

# 3、Handler对象:接收logger传来的日志,然后控制输出
h1 = logging.FileHandler('t1.log')  # 打印到文件
h2 = logging.FileHandler('t2.log')  # 打印到文件
sm = logging.StreamHandler()  # 打印到终端

# 4、Formatter对象:日志格式
formmater1 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
                               datefmt='%Y-%m-%d %H:%M:%S %p', )
formmater2 = logging.Formatter('%(asctime)s :  %(message)s',
                               datefmt='%Y-%m-%d %H:%M:%S %p', )
formmater3 = logging.Formatter('%(name)s %(message)s', )

# 5、为Handler对象绑定格式
h1.setFormatter(formmater1)
h2.setFormatter(formmater2)
sm.setFormatter(formmater3)

# 6、将Handler添加给logger并设置日志级别
logger.addHandler(h1)
logger.addHandler(h2)
logger.addHandler(sm)

# 设置日志级别,可以在两个关卡进行设置logger与handler
# logger是第一级过滤,然后才能到handler
logger.setLevel(30)
h1.setLevel(10)
h2.setLevel(10)
sm.setLevel(10)

# 7、测试
logger.debug('debug')
logger.info('info')
logger.warning('warning')
logger.error('error')
logger.critical('critical')

三、高配logging

1、 配置日志文件

以上三个版本的日志只是为了引出我们下面的日志配置文件

import os
import logging.config

# 定义三种日志输出格式 开始
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                  '[%(levelname)s][%(message)s]'  # 其中name为getLogger()指定的名字;lineno为调用日志输出函数的语句所在的代码行
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
# 定义日志输出格式 结束

logfile_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # log文件的目录,需要自定义文件路径 # atm
logfile_dir = os.path.join(logfile_dir, 'log')  # C:\Users\oldboy\Desktop\atm\log

logfile_name = 'log.log'  # log文件名,需要自定义路径名

# 如果不存在定义的日志目录就创建一个
if not os.path.isdir(logfile_dir):  # C:\Users\oldboy\Desktop\atm\log
    os.mkdir(logfile_dir)

# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)  # C:\Users\oldboy\Desktop\atm\log\log.log
# 定义日志路径 结束

# log配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format
        },
    },
    'filters': {},  # filter可以不定义
    'handlers': {
        # 打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',  # 打印到屏幕
            'formatter': 'simple'
        },
        # 打印到文件的日志,收集info及以上的日志
        'default': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',
            'filename': logfile_path,  # 日志文件
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M  (*****)
            'backupCount': 5,
            'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
        },
    },
    'loggers': {
        # logging.getLogger(__name__)拿到的logger配置。如果''设置为固定值logger1,则下次导入必须设置成logging.getLogger('logger1')
        '': {
            # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'handlers': ['default', 'console'],
            'level': 'DEBUG',
            'propagate': False,  # 向上(更高level的logger)传递
        },
    },
}



def load_my_logging_cfg():
    logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
    logger = logging.getLogger(__name__)  # 生成一个log实例
    logger.info('It works!')  # 记录该文件的运行状态
    
    return logger


if __name__ == '__main__':
    load_my_logging_cfg()

2、 使用日志

import time
import logging
import my_logging  # 导入自定义的logging配置

logger = logging.getLogger(__name__)  # 生成logger实例


def demo():
    logger.debug("start range... time:{}".format(time.time()))
    logger.info("中文测试开始。。。")
    for i in range(10):
        logger.debug("i:{}".format(i))
        time.sleep(0.2)
    else:
        logger.debug("over range... time:{}".format(time.time()))
    logger.info("中文测试结束。。。")


if __name__ == "__main__":
    my_logging.load_my_logging_cfg()  # 在你程序文件的入口加载自定义logging配置
    demo()

四、Django日志配置文件

Django(发音:[`dʒæŋɡəʊ])是一个开放源代码的Web应用框架,由Python写成。采用了MTV的框架模式,即模型M,视图V和模版T。

# logging_config.py

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]'
                      '[%(levelname)s][%(message)s]'
        },
        'simple': {
            'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
        },
        'collect': {
            'format': '%(message)s'
        }
    },
    'filters': {
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {
        # 打印到终端的日志
        'console': {
            'level': 'DEBUG',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        # 打印到文件的日志,收集info及以上的日志
        'default': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
            'filename': os.path.join(BASE_LOG_DIR, "xxx_info.log"),  # 日志文件
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 3,
            'formatter': 'standard',
            'encoding': 'utf-8',
        },
        # 打印到文件的日志:收集错误及以上的日志
        'error': {
            'level': 'ERROR',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
            'filename': os.path.join(BASE_LOG_DIR, "xxx_err.log"),  # 日志文件
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 5,
            'formatter': 'standard',
            'encoding': 'utf-8',
        },
        # 打印到文件的日志
        'collect': {
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件,自动切
            'filename': os.path.join(BASE_LOG_DIR, "xxx_collect.log"),
            'maxBytes': 1024 * 1024 * 5,  # 日志大小 5M
            'backupCount': 5,

            'formatter': 'collect',
            'encoding': "utf-8"
        }
    },
    'loggers': {
        # logging.getLogger(__name__)拿到的logger配置
        '': {
            'handlers': ['default', 'console', 'error'],
            'level': 'DEBUG',
            'propagate': True,
        },
        # logging.getLogger('collect')拿到的logger配置
        'collect': {
            'handlers': ['console', 'collect'],
            'level': 'INFO',
        }
    },
}


# -----------
# 用法:拿到俩个logger

logger = logging.getLogger(__name__)  # 线上正常的日志
collect_logger = logging.getLogger("collect")  # 领导说,需要为领导们单独定制领导们看的日志

到此这篇关于Python日志模块的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。


Tags in this post...

Python 相关文章推荐
Python编写屏幕截图程序方法
Feb 18 Python
Python基于identicon库创建类似Github上用的头像功能
Sep 25 Python
Python入门之三角函数全解【收藏】
Nov 08 Python
python matplotlib中文显示参数设置解析
Dec 15 Python
python实现在IDLE中输入多行的方法
Apr 19 Python
pandas读取csv文件,分隔符参数sep的实例
Dec 12 Python
python实现转圈打印矩阵
Mar 02 Python
python pickle存储、读取大数据量列表、字典数据的方法
Jul 07 Python
Python使用Pandas对csv文件进行数据处理的方法
Aug 01 Python
TensorFlow通过文件名/文件夹名获取标签,并加入队列的实现
Feb 17 Python
浅谈python 调用open()打开文件时路径出错的原因
Jun 05 Python
Python操作Excel的学习笔记
Feb 18 Python
Python使用Beautiful Soup(BS4)库解析HTML和XML
Jun 05 #Python
Python四款GUI图形界面库介绍
Python序列化模块JSON与Pickle
Jun 05 #Python
python 判断字符串当中是否包含字符(str.contain)
Python测试框架pytest高阶用法全面详解
Python使用Web框架Flask开发项目
Jun 01 #Python
numpy array找出符合条件的数并赋值的示例代码
Jun 01 #Python
You might like
PHP+MYSQL的文章管理系统(二)
2006/10/09 PHP
PHP 正则表达式之正则处理函数小结(preg_match,preg_match_all,preg_replace,preg_split)
2012/10/05 PHP
PHP高并发和大流量解决方案整理
2019/12/24 PHP
利用PHP内置SERVER开启web服务(本地开发使用)
2021/03/09 PHP
JavaScript 事件冒泡简介及应用
2010/01/11 Javascript
js 异步处理进度条
2010/04/01 Javascript
JS getStyle获取最终样式函数代码
2010/04/01 Javascript
写了10年的Javascript也未必全了解的连续赋值运算
2011/03/25 Javascript
jQuery EasyUI API 中文文档 - Form表单
2011/10/06 Javascript
简介JavaScript中setUTCSeconds()方法的使用
2015/06/12 Javascript
javascript中不易分清的slice,splice和split三个函数
2016/03/29 Javascript
jQuery unbind 删除绑定事件详解
2016/05/24 Javascript
checkbox批量选中,获取选中项的值的简单实例
2016/06/28 Javascript
深入浅析JavaScript中的scrollTop
2016/07/11 Javascript
JS获取checkbox的个数简单实例
2016/08/19 Javascript
JS仿hao123导航页面图片轮播效果
2016/09/01 Javascript
Vue.js实战之利用vue-router实现跳转页面
2017/04/01 Javascript
vue-lazyload图片延迟加载插件的实例讲解
2018/02/09 Javascript
关于echarts在节点显示动态数据及添加提示文本所遇到的问题
2018/04/20 Javascript
layui点击导航栏刷新tab页的示例代码
2018/08/14 Javascript
解决Vue中 父子传值 数据丢失问题
2019/08/27 Javascript
JavaScript RegExp 对象用法详解
2019/09/24 Javascript
vue 使用 canvas 实现手写电子签名
2020/03/06 Javascript
将Python代码嵌入C++程序进行编写的实例
2015/07/31 Python
python的中异常处理机制
2018/08/30 Python
解决webdriver.Chrome()报错:Message:'chromedriver' executable needs to be in Path
2019/06/12 Python
python实现低通滤波器代码
2020/02/26 Python
python 实现朴素贝叶斯算法的示例
2020/09/30 Python
关于人生的感言
2014/01/17 职场文书
互联网创业计划书的书写步骤
2014/01/28 职场文书
升国旗演讲稿
2014/09/05 职场文书
教师党员个人剖析材料
2014/09/29 职场文书
买房协议书范本
2014/10/23 职场文书
停课通知书
2015/04/24 职场文书
MySQL 服务和数据库管理
2021/11/11 MySQL
Java界面编程实现界面跳转
2022/06/16 Java/Android