文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Python内置logging怎么使用

2023-07-02 16:52

关注

这篇文章主要讲解了“Python内置logging怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python内置logging怎么使用”吧!

logging 的主要作用

提供日志记录的接口和众多处理模块,供用户存储各种格式的日志,帮助调试程序或者记录程序运行过程中的输出信息。

logging 日志等级

logging 日志等级分为五个等级,优先级从高到低依次是 :

**CRITICAL; ** 程序严重错误

**ERROR; **程序错误/部分功能错误

**WARNING; **程序有发生错误的可能

**INFO; **程序正常运行时的信息

DEBUG程序调试信息

默认的日志的记录等级为 WARNING, 即当日志的等级大于获等于 WARNING 时才会被记录。

一般常用的记录等级为 INFO,其用于记录程序的正常运行的一些信息(类似于print)。

当日志的等级达到 WARNING 以上时,表明此时程序不能正常运行;

logging 的基础函数

logging.basicConfig(**kwargs)

在没有显式的进行创建记录器(logger)时,会默认创建一个root logger,而logging.basicConfig(**kwargs) 可以创建带有默认的Formatter的streamHandle并将其添加到根日志记录器中来初始化基本配置。

比如

import logginglogging.debug('Debug code!')logging.info('Run code!')logging.warning('Watch out!')  logging.error('This is an error')logging.critical('This is a ciritical')

上面代码中 logging 并没有显式的创建logger( logging.getLogger ), 其在直接使用debug(), info(), warning(), error(), critical() 时会使用默认的 root logger,并会自动调用 自定义的或者默认的logging.basicConfig(**kwargs) 初始化 root logger。

自定义的 logging.basicConfig(**kwargs) 中的参数 有以下的主要的选项:

参数功能
filename指定保存日志的文件名,用指定文件名创建一个FileHandler,记录的日志会保存到该文件中
format指定输出的格式和内容,默认是以冒号分割的levalname、name 和 message
datefmt使用指定的日期/时间格式,与 time.strftime() 所接受的格式相同。
level指定根日志记录器级别,默认为 logging.WARNING
stream指定日志的输出流,可以指定输出到sys.stderr,std.stdout 或 文件,默认输出到sys.stderr。使用指定的流初始化StramHandler,注意:stream和filename参数不兼容,如果两者同时使用,则会引发ValueError 错误

例如下面通过自定义 logging.basicConfig(**kwargs) 来初始化 root logger 来获得DEBUG级别及以上的日志记录并保存到 log.txt 文件中。

import logginglogging.basicConfig(filename='./log.txt',                        format='%(asctime)s-%(name)s-%(levelname)s-%(message)s-%(funcName)s:%(lineno)d',                        level=logging.DEBUG)logging.debug('Debug code!')logging.info('Run code!')logging.warning('Watch out!')  logging.error('This is an error')logging.critical('This is a ciritical')

logging 的四大组件(类)

Logger

除了根记录器(root logger)外,最主要的是可以自己创建日志记录器。

通过模块级别的函数 logging.getLogger(name) 实例化记录器

默认情况下,记录器采用层级结构,通过 . 来区分不同的层级。比如 有个名叫 foo 的记录器 则 foo.afoo.b 都是 foo 的子级记录器。当然,最开始的或者说最上层的记录器就是 root logger。如果 name=None,构建的是root logger。

可以直接用当前模块的名称当作记录器的名字 logging.getLogger(__name__)

子级记录器通常不需要单独设置日志级别以及 Handler,如果子级记录器没有单独设置,则它的行为会委托给父级。比如说,记录器foo的级别为INFO,而foo.afoo.b 都不设置日志级别。此时foo.afoo.b 会遵循foo 的级别设置,即只记录大于等于INFO级别的日志;而如果foo也没设置的话,就会找到根记录器root logger,root默认的级别为WARGING。

logger类的一些常用的方法

方法功能描述
Logger.setLevel()设置日志器(Logger)将会处理的日志消息级别
Logger.addHandler()添加一个handler对象
Logger.removeHandler()移除一个handler对象
Logger.addFilter()添加一个filter对象
Logger.removeFilter()移除一个filter对象
Logger.debug()设置DEBUG级别的日志记录
Logger.info()设置INFO级别的日志记录
Logger.warning()设置WARNING级别的日志记录
Logger.error()设置ERROR级别的日志记录
Logger.critical()设置CRITICAL级别的日志记录
Logger.exception()输出堆栈追踪信息
Logger.log()设置一个自定义的level参数来创建一个日志记录

logger 结合 后面要介绍的其他的三个组件可以实现以下的功能:

Handle

处理器;其可以控制记录的日志输出到什么地方(标准输出/文件/...),同时处理器也可以添加 过滤器(filter)和格式控制器(formatter)来控制输出的内容和输出的格式。

其具有几种常见的处理器:

handle 类的一些常用的方法

Handler.setLevel()设置处理器将会处理的日志消息的最低严重级别
Handler.setFormatter()为处理器设置一个格式对象
Handler.addFilter()为处理器添加一个过滤器对象
Handler.removeFilter()为处理器删除一个过滤器对象
logging.StramHandler()将日志消息发送到输出Stream,如std.out,std.err
logging.FilterHandler()将日志消息发送到磁盘文件,默认情况文件大小会无线增长
RotationFileHandler()将日志消息发送到磁盘文件,支持日志文件按大小切割
TimeRotatingFileHandler()将日志消息发送到磁盘文件,并支持日志文件按时间切割
logging.handers.HTTPHandler()将日志消息通过GET或POST的方式发送给一个HTTP服务器
logging.handlers.SMTPHandler()将日志消息发送email地址

Filter

filter组件用来过滤 logger 对象,一个 filter 可以直接添加到 logger对象上,也可以添加到 handler 对象上,而如果在logger和handler中都设置了filter,则日志是先通过logger的filter,再通过handler的filter。由于所有的信息都可以经过filter,所以filter不仅可以过滤信息,还可以增加信息。

Filter 类的实例化对象可以通过 logging.Filter(name) 来创建,其中name 为 记录器的名字,如果没有创建过该名字的记录器,就不会输出任何日志:

filter = logging.Filter("foo.a")

基本过滤器类只允许低于指定的日志记录器层级结构中低于特定层级的事件,例如 这个用 foo.a 初始化的过滤器,则foo.a.b;foo.a.c 等日志记录器记录的日志都可以通过过滤器,而foo.c; a.foo 等就不能通过。如果name为空字符串,则所有的日志都能通过。

Filter 类 有 三个方法 :

Formatter

格式化日志的输出;实例化:formatter = logging.Formatter(fmt=None,datefmt=None); 如果不指明 fmt,将默认使用 ‘%(message)s’ ,如果不指明 datefmt,将默认使用 ISO8601 日期格式。

其中 fmt 参数 有以下选项:

%(name)sLogger的名字
%(levelno)s数字形式的日志级别
%(levelname)s文本形式的日志级别;如果是logger.debug则它是DEBUG,如果是logger.error则它是ERROR
%(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用户输出的消息; 假如有logger.warning("NO Good"),则在%(message)s位置上是字符串NO Good

例如:

formatter = logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s')# -表示右对齐 8表示取8位handler.formatter = formatter

datefmt 参数 有以下选项:

参数含义
%y两位数的年份表示(00-99)
%Y四位数的年份表示(000-9999)
%m月份(01-12)
%d月内中的一天(0-31)
%H24小时制小时数(0-23)
%I12小时制小时数(01-12)
%M分钟数(00=59)
%S 秒(00-59)

例如:

formatter = logging.Formatter('%(asctime)s %(levelname)-8s: %(message)s')# -表示右对齐 8表示取8位handler.formatter = formatter

datefmt 参数 有以下选项:

参数含义
%y两位数的年份表示(00-99)
%Y四位数的年份表示(000-9999)
%m月份(01-12)
%d月内中的一天(0-31)
%H24小时制小时数(0-23)
%I12小时制小时数(01-12)
%M分钟数(00=59)
%S 秒(00-59)

例子:

formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s","%Y%m%d-%H:%M:%S")handler.formatter = formatter

logging 的配置

在 loguser.conf 中 写入相关的信息

[loggers]keys=root,fileLogger,rotatingFileLogger[handlers]keys=consoleHandler,fileHandler,rotatingFileHandler[formatters]keys=simpleFormatter[logger_root]level=INFOhandlers=consoleHandler[logger_fileLogger]level=INFOhandlers=fileHandlerqualname=fileLoggerpropagate=0[logger_rotatingFileLogger]level=INFOhandlers=consoleHandler,rotatingFileHandlerqualname=rotatingFileLoggerpropagate=0[handler_consoleHandler]class=StreamHandlerlevel=INFOformatter=simpleFormatterargs=(sys.stdout,)[handler_fileHandler]class=FileHandlerlevel=INFOformatter=simpleFormatterargs=("logs/fileHandler_test.log", "a")[handler_rotatingFileHandler]class=handlers.RotatingFileHandlerlevel=WARNINGformatter=simpleFormatterargs=("logs/rotatingFileHandler.log", "a", 10*1024*1024, 50)[formatter_simpleFormatter]format=%(asctime)s - %(module)s - %(levelname)s -%(thread)d : %(message)sdatefmt=%Y-%m-%d %H:%M:%S
from logging import configwith open('./loguser.conf', 'r', encoding='utf-8') as f:## 加载配置    config.fileConfig(f)    ## 创建同名Logger,其按照配置文件的handle,formatter,filter方法初始化    logger = logging.getLogger(name="fileLogger")

在 loguser.yaml文件 中 配置相关信息

version: 1disable_existing_loggers: False# formatters配置了日志输出时的样式# formatters定义了一组formatID,有不同的格式;formatters:  brief:      format: "%(asctime)s - %(message)s"  simple:      format: "%(asctime)s - [%(name)s] - [%(levelname)s] :%(levelno)s: %(message)s"      datefmt: '%F %T'# handlers配置了需要处理的日志信息,logging模块的handler只有streamhandler和filehandlerhandlers:  console:      class : logging.StreamHandler      formatter: brief      level   : DEBUG      stream  : ext://sys.stdout  info_file_handler:      class : logging.FileHandler      formatter: simple      level: ERROR      filename: ./logs/debug_test.log  error_file_handler:    class: logging.handlers.RotatingFileHandler    level: ERROR    formatter: simple    filename: ./logs/errors.log    maxBytes: 10485760 # 10MB #1024*1024*10    backupCount: 50    encoding: utf8loggers:#fileLogger, 就是在代码中通过logger = logging.getLogger("fileLogger")来获得该类型的logger  my_testyaml:      level: DEBUG      handlers: [console, info_file_handler,error_file_handler]# root为默认情况下的输出配置, 当logging.getLogger("fileLoggername")里面的fileLoggername没有传值的时候,# 就是用的这个默认的root,如logging.getLogger(__name__)或logging.getLogger()root:    level: DEBUG    handlers: [console]

同样的可以通过导入 yaml 文件加载配置

with open('./loguser.yaml', 'r', encoding='utf-8') as f:        yaml_config = yaml.load(stream=f, Loader=yaml.FullLoader)        config.dictConfig(config=yaml_config)    root = logging.getLogger()    # 子记录器的名字与配置文件中loggers字段内的保持一致    # loggers:    #   my_testyaml:    #       level: DEBUG    #       handlers: [console, info_file_handler,error_file_handler]    my_testyaml = logging.getLogger("my_testyaml")

logging 和 print 的区别

看起来logging要比print复杂多了,那么为什么推荐在项目中使用 logging 记录日志而不是使用print 输出程序信息呢。

相比与print logging 具有以下优点:

感谢各位的阅读,以上就是“Python内置logging怎么使用”的内容了,经过本文的学习后,相信大家对Python内置logging怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯