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的web框架中的Model的教程
Apr 29 Python
Python基于Tkinter的HelloWorld入门实例
Jun 17 Python
python3+PyQt5自定义视图详解
Apr 24 Python
Python图像处理之gif动态图的解析与合成操作详解
Dec 30 Python
Django异步任务之Celery的基本使用
Mar 23 Python
Python Matplotlib 基于networkx画关系网络图
Jul 10 Python
python pycharm的安装及其使用
Oct 11 Python
浅析Django中关于session的使用
Dec 30 Python
python右对齐的实例方法
Jul 05 Python
Python实现Telnet自动连接检测密码的示例
Apr 16 Python
Python Numpy之linspace用法说明
Apr 17 Python
Python基础之数据结构详解
Apr 28 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编写的SVN类
2013/07/18 PHP
php根据日期判断星座的函数分享
2014/02/13 PHP
php自定文件保存session的方法
2014/12/10 PHP
php检查页面是否被百度收录
2015/10/28 PHP
PHP递归实现汉诺塔问题的方法示例
2017/11/25 PHP
laravel框架关于搜索功能的实现
2018/03/15 PHP
PHP ADODB实现分页功能简单示例
2018/05/25 PHP
Laravel 创建可以传递参数 Console服务的例子
2019/10/14 PHP
跟随鼠标旋转的文字
2006/11/30 Javascript
一个判断email合法性的函数[非正则]
2008/12/09 Javascript
简单的js分页脚本
2009/05/21 Javascript
通过AJAX的JS、JQuery两种方式解析XML示例介绍
2013/09/23 Javascript
jQuery实现类似滑动门切换效果的层切换
2013/09/23 Javascript
基于JavaScript实现复选框的全选和取消全选
2017/02/09 Javascript
JS实现手写parseInt的方法示例
2017/09/24 Javascript
Jquery实现无缝向上循环滚动列表的特效
2019/02/13 jQuery
稍微学一下Vue的数据响应式(Vue2及Vue3区别)
2019/11/21 Javascript
基于JQuery实现页面定时弹出广告
2020/05/08 jQuery
vue引入静态js文件的方法
2020/06/20 Javascript
Python实现将绝对URL替换成相对URL的方法
2015/06/28 Python
python2.7到3.x迁移指南
2018/02/01 Python
Python访问MongoDB,并且转换成Dataframe的方法
2018/10/15 Python
Python符号计算之实现函数极限的方法
2019/07/15 Python
Python中字典与恒等运算符的用法分析
2019/08/22 Python
django之从html页面表单获取输入的数据实例
2020/03/16 Python
python递归调用中的坑:打印有值, 返回却None
2020/03/16 Python
新西兰床上用品和家居用品购物网站:Adairs
2018/04/27 全球购物
施华洛世奇匈牙利官网:SWAROVSKI匈牙利
2019/07/06 全球购物
美国知名眼镜网站:Target Optical
2020/04/04 全球购物
网络事业创业计划书范文
2014/01/09 职场文书
电大毕业自我鉴定
2014/02/03 职场文书
《藤野先生》教学反思
2014/02/19 职场文书
环保宣传语大全
2015/07/13 职场文书
2015年小学生国庆节演讲稿
2015/07/30 职场文书
Go语言基础切片的创建及初始化示例详解
2021/11/17 Golang
阿里云 Windows server 2019 配置FTP
2022/04/28 Servers