python程序调试logging_python-logging模块的简单使用

本文介绍使用Python的logging模块进行日志记录的方法。包括日志级别、四大组件的使用及示例代码,帮助开发者有效记录程序运行状态。

本人是新手程序员,写文章是为了记录学习,文章中多有错误,还望大家谅解,并指出问题。

本文用到的技术与工具:python,pycharm,logging等。

最近写了一个程序demo,一天24小时挂着跑,有时候会报错,虽然不会影响程序继续跑,但是问题总是要解决的,又不能24小时守着,所有想写个日志记录错误信息,日志当然已经搞定了啦,下面是正文。

日志是什么,日志的作用是什么,这里就不一一赘述了,这里使用python的logging模块来进行日志操作。

1、logging模块的日志级别

logging模块默认定义了以下几个日志等级,它允许开发人员自定义其他日志级别,但是这是不被推荐的,尤其是在开发供别人使用的库时,因为这会导致日志级别的混乱。logging默认日志等级

开发应用程序或部署开发环境时,可以使用DEBUG或INFO级别的日志获取尽可能详细的日志信息来进行开发或部署调试;

应用上线或部署生产环境时,应该使用WARNING或ERROR或CRITICAL级别的日志来降低机器的I/O压力和提高获取错误日志信息的效率。日志级别的指定通常都是在应用程序的配置文件中进行指定的。

注意:

~上图列表中的日志等级是从上到下依次升高的,即:DEBUG < INFO < WARNING < ERROR < CRITICAL,而日志的信息量是依次减少的;

~当为某个应用程序指定一个日志级别后,应用程序会记录所有日志级别大于或等于指定日志级别的日志信息,而不是仅仅记录指定级别的日志信息,只有级别大于或等于该指定日志级别的日志记录才会被输出,小于该等级的日志记录将会被丢弃。

2、logging模块的使用方式

logging模块提供了两种使用方式:一、使用logging提供的模块级别的函数;二、使用Logging日志系统的四大组件。logging所提供的模块级别的日志记录函数是对logging日志系统相关类的封装

上述是我参考的资料中所说的,看了第一种方式的使用过程,我有点不太理解如何自如使用,既然说到是对第二种方式的封装,那我大概理解成了我太菜了,还没到那个等级,所有本文就不介绍第一种方式了,直接第二种方式开撸!

3、使用Logging日志系统的四大组件,日志流的处理流程

首先给大家看一下logging模块定义的模块级别的常用函数,如下图:logging模块定义的模块级别的常用函数

关于logging.basicConfig()函数,我百度了大量资料,在众多资料中有些提到该函数的参数时包含了handlers,有些没有,参数handlers的使用方法仍未找到,希望有大佬知道的可以教一下我,logging.basicConfig()函数的参数说明如下图:logging.basicConfig()函数的参数说明

我们已经知道logging的常用函数,下面看看lgging模块的四大组件:lgging模块的四大组件

这些组件之间是什么样的关系呢?日志器(logger)需要通过处理器(handler)将日志信息输出到目标位置,如:文件、sys.stdout、网络等;

不同的处理器(handler)可以将日志输出到不同的位置;

日志器(logger)可以设置多个处理器(handler)将同一条日志记录输出到不同的位置;

每个处理器(handler)都可以设置自己的过滤器(filter)实现日志过滤,从而只保留感兴趣的日志;

每个处理器(handler)都可以设置自己的格式器(formatter)实现同一条日志以不同的格式输出到不同的地方。

简单点说就是:日志器(logger)是入口,真正干活儿的是处理器(handler),处理器(handler)还可以通过过滤器(filter)和格式器(formatter)对要输出的日志内容做过滤和格式化等处理操作。

3.1、logger类

logger对象有三个任务要做:1)向应用程序代码暴露几个方法,使应用程序可以在运行时记录日志消息;

2)基于日志严重等级(默认的过滤设施)或filter对象来决定要对哪些日志进行后续处理;

3)将日志消息传送给所有感兴趣的日志handlers。

Logger对象最常用的方法分为两类:配置方法 和 消息发送方法

最常用配置方法如下:logger对象常用配置方法

logger对象配置完成后,可以使用下面的方法来创建日志记录:创建日志记录的方法

通常使用logging.getLogger()方法创建一个logger实例,logging.getLogger()方法有一个可选参数name,该参数表示将要返回的日志器的名称标识,如果不提供该参数,则其值为'root'。若以相同的name参数值多次调用getLogger()方法,将会返回指向同一个logger对象的引用。多次使用注意不能创建多个logger,否则会出现重复输出日志现象。

3.2、handler类

Handler对象的作用是(基于日志消息的level)将消息分发到handler指定的位置(文件、网络、邮件等)。Logger对象可以通过addHandler()方法为自己添加0个或者更多个handler对象。

需要说明的是,应用程序代码不应该直接实例化和使用Handler实例。因为Handler是一个基类,它只定义了素有handlers都应该有的接口,同时提供了一些子类可以直接使用或覆盖的默认行为。下面是一些常用的Handler:常用Handler

3.3、formatter类

Formater对象用于配置日志信息的最终顺序、结构和内容。

3.4、filter类

Filter可以被Handler和Logger用来做比level更细粒度的、更复杂的过滤功能。

日志流简要处理流程(按照日志时间切割)

1、创建一个logger,如果参数为空则返回root logger

logger = logging.getLogger('')

2、设置下logger的日志的等级

logger.setLevel(logging.DEBUG)

3、创建合适的Handler(FileHandler要有路径),我这里创建了一个根据时间切分的Handler

下方代码中,'when='S''表示以秒切割文件;'interval=1'表示切割的标准为间隔为1秒;'backupCount=3'表示日志文件总数为3,也就是说日志文件数等于3时,后面生成的日志文件会替换掉时间最早的日志文件;fh.suffix设置日志文件名时间后缀。

fh = logging.handlers.TimedRotatingFileHandler("test.log", when='S', interval=1, backupCount=3, encoding="utf-8")

fh.suffix = "%Y-%m-%d_%H-%M-%S.log"

ch = logging.StreamHandler()

4、创建日志的格式

formatter = logging.Formatter(

fmt="%(asctime)s %(name)s %(filename)s %(message)s",

datefmt="%Y/%m/%d %X"

)

5、向Handler中添加上面创建的格式

fh.setFormatter(formatter)

ch.setFormatter(formatter)

6、将上面创建的Handler添加到logger中

logger.addHandler(fh)

logger.addHandler(ch)

7、打印输出

logger.warning("警告")

logger.info("提示")

logger.error("错误")

logger.debug("查错")

例子:

import logging

import logging.handlers #按时间切割一定要导入该模块

def log():

logger = logging.getLogger("")  #创建logger,如果参数为空则返回root logger

logger.setLevel(logging.DEBUG)  #设置logger日志等级

#这里进行判断,如果logger.handlers列表为空,则添加,否则,直接去写日志

if not logger.handlers:

#创建handler

#按照时间切分文件,interval指间隔时间数目,backupCount指保留的文件个数

fh = logging.handlers.TimedRotatingFileHandler("test.log", when='S', interval=1, backupCount=3, encoding="utf-8")

fh.suffix = "%Y-%m-%d_%H-%M-%S.log"

ch = logging.StreamHandler()

#设置输出日志格式

formatter = logging.Formatter(

fmt="%(asctime)s %(name)s %(filename)s %(message)s",

datefmt="%Y/%m/%d %X"

)

#为handler指定输出格式

fh.setFormatter(formatter)

ch.setFormatter(formatter)

#为logger添加的日志处理器

logger.addHandler(fh)

logger.addHandler(ch)

return logger #直接返回logger

logger = log()

logger.warning("警告")

logger.info("提示")

logger.error("错误")

logger.debug("查错")

上面的例子中标红部分"if not logger.handlers:"是为了解决重复写日志问题,当然还有其他解决方案,比如在为logger添加日志处理器后removeHandler,具体用哪种方案看个人喜好吧。

例子运行看看效果如何,控制台

控制台打印出了日志信息,运行四次程序看看生成的日志文件,运行四次程序生成的日志文件

第一次运行生成了“test.log”文件,后面三次生成了按照时间切割后的文件,再运行一次看看,运行第五次程序后生成的日志文件

可以看到后缀为43的文件被替换成了后缀为49的文件,成功!

主要参考资料链接地址:https://www.cnblogs.com/yuanyongqiang/p/11913812.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值