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 相关文章推荐
pycharm 使用心得(四)显示行号
Jun 05 Python
Python如何实现MySQL实例初始化详解
Nov 06 Python
PyTorch学习笔记之回归实战
May 28 Python
python变量赋值方法(可变与不可变)
Jan 12 Python
Python中单线程、多线程和多进程的效率对比实验实例
May 14 Python
pyqt5之将textBrowser的内容写入txt文档的方法
Jun 21 Python
python实现输入的数据在地图上生成热力图效果
Dec 06 Python
python GUI库图形界面开发之PyQt5树形结构控件QTreeWidget详细使用方法与实例
Mar 02 Python
Python偏函数Partial function使用方法实例详解
Jun 17 Python
Python浮点型(float)运算结果不正确的解决方案
Sep 22 Python
解决python 在for循环并且pop数组的时候会跳过某些元素的问题
Dec 11 Python
Windows安装Anaconda3的方法及使用过程详解
Jun 11 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 学习资料零碎东西
2010/12/04 PHP
php自定义urlencode,urldecode函数实例
2015/03/24 PHP
Javascript 中文字符串处理额外注意事项
2009/11/15 Javascript
js继承的实现代码
2010/08/05 Javascript
iframe的onload在Chrome/Opera中执行两次Bug的解决方法
2011/03/17 Javascript
javascript数组的使用
2013/03/28 Javascript
javascript使用call调用微信API
2014/12/15 Javascript
javascript实现的登陆遮罩效果汇总
2015/11/09 Javascript
Bootstrap Table从零开始
2017/06/30 Javascript
Javascript中的getter和setter初识
2017/08/17 Javascript
AngularJs用户输入动态模板XSS攻击示例详解
2018/04/21 Javascript
2019年度web前端面试题总结(主要为Vue面试题)
2020/01/12 Javascript
js函数柯里化的方法和作用实例分析
2020/04/11 Javascript
详解JavaScript匿名函数和闭包
2020/07/10 Javascript
npm ci命令的基本使用方法
2020/09/20 Javascript
[49:31]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS BO3 第二场 1月29日
2021/03/11 DOTA
Python实现list反转实例汇总
2014/11/11 Python
python实现12306抢票及自动邮件发送提醒付款功能
2018/03/08 Python
Python + selenium自动化环境搭建的完整步骤
2018/05/19 Python
Python面向对象程序设计OOP入门教程【类,实例,继承,重载等】
2019/01/05 Python
python3去掉string中的标点符号方法
2019/01/22 Python
python字符串替换第一个字符串的方法
2019/06/26 Python
Python 调用 Outlook 发送邮件过程解析
2019/08/08 Python
pyqt5中动画的使用详解
2020/04/01 Python
Python 实现 T00ls 自动签到脚本代码(邮件+钉钉通知)
2020/07/06 Python
英国知名奢侈品包包品牌:Milli Millu
2016/12/22 全球购物
伦敦一家非常流行的时尚精品店:Oxygen Boutique
2017/01/15 全球购物
小学音乐教学反思
2014/02/05 职场文书
服务员岗位责任制
2014/02/11 职场文书
第一批党的群众路线教育实践活动工作总结
2014/03/03 职场文书
《菜园里》教学反思
2014/04/17 职场文书
个人校本研修方案
2014/05/26 职场文书
整改通知书格式
2015/04/22 职场文书
2015年营销工作总结范文
2015/04/23 职场文书
微软Win11有哪些隐藏功能? windows11多个功能汇总
2021/11/21 数码科技
html原生table实现合并单元格以及合并表头的示例代码
2023/05/07 HTML / CSS