Python编程:标准库logging使用

news2024/11/18 7:35:45

Python编程:标准库logging使用

一、 基础使用

1.1 logging使用场景

​ 日志是什么?这个不用多解释。百分之九十的程序都需要提供日志功能。Python内置的logging模块,为我们提供了现成的高效好用的日志解决方案。但是,不是所有的场景都需要使用logging模块,下面是Python官方推荐的使用方法:

任务场景最佳工具
普通情况下,在控制台显示输出print()
报告正常程序操作过程中发生的事件logging.info()(或者更详细的logging.debug())
发出有关特定事件的警告warnings.warn()或者logging.warning()
报告错误弹出异常
在不引发异常的情况下报告错误logging.error(), logging.exception()或者logging.critical()

logging模块定义了下表所示的日志级别,按事件严重程度由低到高排列(注意是全部大写!因为它们是常量。):

级别级别数值使用时机
DEBUG10详细信息,常用于调试。
INFO20程序正常运行过程中产生的一些信息。
WARNING30警告用户,虽然程序还在正常工作,但有可能发生错误。
ERROR40由于更严重的问题,程序已不能执行一些功能了。
CRITICAL50严重错误,程序已不能继续运行。

默认级别是WARNING,表示只有WARING和比WARNING更严重的事件才会被记录到日志内,低级别的信息会被忽略。因此,默认情况下,DEBUG和INFO会被忽略,WARING、ERROR和CRITICAL会被记录。

有多种方法用来处理被跟踪的事件。最简单的方法就是把它们打印到终端控制台上。或者将它们写入一个磁盘文件内。

1.2 简单范例

在什么都不配置和设定的情况下,logging会简单地将日志打印在显示器上,如下例所示:

import logginglogging.warning('Watch out!')  # 消息会被打印到控制台上
logging.info('I told you so')  # 这行不会被打印,因为级别低于默认级别

如果,将上面的代码放在一个脚本里并运行,结果是:

WARNING:root:Watch out!

默认情况下,打印出来的内容包括日志级别、调用者和具体的日志信息。所有的这些内容都是可以自定义的,在后面我们会细说。

1.3 记录到文件内

要把日志输出到文件内,就不能使用上面的方法了,但是logging模块同样给我们提供了一个相对便捷的手段,那就是logging.basicConfig()方法。

重新进入解释器环境,执行下面的代码:

import logging
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')

然后打开本地的example.log文件,可以看到下面的日志消息:

DEBUG:root:This message should go to the log fileINFO:root:So should thisWARNING:root:And this, too

我们通过level=logging.DEBUG参数,设定了日志记录的门槛。如果想在命令行调用时设置日志级别,可以使用下面的选项:

--log=INFO

可以通过下面的方法来获取用户输入的日志级别参数:

numeric_level = getattr(logging, loglevel.upper(), None)
if not isinstance(numeric_level, int):    
	raise ValueError('Invalid log level: %s' % loglevel)
logging.basicConfig(level=numeric_level, ...)

默认情况下,日志会不断的追加到文件的后面。如果你不想保存之前的日志,每次都清空文件,然后写入当前日志,则可以如下设置:

logging.basicConfig(filename='example.log', filemode='w', level=logging.DEBUG)

关键是将filemode设置为‘w’。

1.4 多模块中同时使用日志功能

如果你的程序包含多个文件(模块),下面是个如何在其中组织日志的例子

# myapp.py
import logging
import mylib
def main():    
    logging.basicConfig(filename='myapp.log', level=logging.INFO)    
    logging.info('Started')    
    mylib.do_something()    
    logging.info('Finished')
    
if __name__ == '__main__':    
    main()	
 # mylib.py
import logging

def do_something():    
    logging.info('Doing something')

运行myapp.py模块,你可以在myapp.log日志文件中看到下面的内容:

INFO:root:Started
INFO:root:Doing something
INFO:root:Finished

1.5 日志的变量数

在logging模块中通过百分符%方式的格式化控制,生成消息字符串,类同于字符串数据类型的格式化输出,但也有不同之处。

import logging
logging.warning('%s before you %s', 'Look', 'leap!')

结果:

WARNING:root:Look before you leap!

可以看到两个%s分别被‘Look’和‘leap!’替代了。

1.6 消息格式

要控制消息格式,获得更多的花样,可以提供format参数:

import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
logging.debug('This message should appear on the console')
logging.info('So should this')
logging.warning('And this, too')

输出结果:

DEBUG:This message should appear on the console
INFO:So should this
WARNING:And this, too

对于%(levelname)s这种东西,是logging模块内置的,可以被输出到日志中的对象,更多的内容在下面将会列举。

1.7 附加时间信息

要在日志内容中附加时间信息,可以在format字符串中添加%(asctime)s。

import logginglogging.basicConfig(format='%(asctime)s %(message)s')
logging.warning('is when this event was logged.')

输出结果:

2023-06-12 12:51:42,760 is when this event was logged.

默认情况下,时间的显示使用ISO8601格式。如果想做更深入的定制,可以提供datefmt参数,如下所示:

import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')

输出结果

062/12/2023 12:56:36 PM is when this event was logged.

datefmt参数的定制和time模块的time.strftime()一样!

二、 高级用法

如果只是简单地使用logging,那么使用上面介绍的方法就可以了,如果要深度定制logging,那么就需要对它有更深入的了解。下面的内容才是基本的logging模块的使用方法。

logging模块采用了模块化设计,主要包含四种组件:

Loggers:记录器,提供应用程序代码能直接使用的接口;

Handlers:处理器,将记录器产生的日志发送至目的地;

Filters:过滤器,提供更好的粒度控制,决定哪些日志会被输出;

Formatters:格式化器,设置日志内容的组成结构和消息字段。

2.1 日志流程图

日志事件信息在loggers和handlers中的逻辑流程如下图所示:
在这里插入图片描述

下面是同时向屏幕和文件进行日志输出的流程:
在这里插入图片描述

2.2 Loggers记录器

logging模块的日志功能是基于Logger类实现的。我们可以通过下面的方法获取一个Logger类的实例(建议以模块名命名logger实例)。

logger = logging.getLogger(__name__)

Logger是一个树形层级结构,在使用debug(),info(),warn(),error(),critical()等方法之前必须先创建一个Logger的实例,即创建一个记录器,如果没有显式的进行创建,则默认创建一个root logger,并应用默认的日志级别(WARN),默认的处理器Handler(StreamHandler,即将日志信息打印在标准输出上),和默认的格式化器Formatter,就像我们在前面举的那些例子一样。logger对象有三重功能。首先,提供应用程序调用的接口;其次,决定日志记录的级别;最后,将日志内容传递到相关联的handlers中。总结logger对象的用法,可以分成两类:配置和消息发送。

下面是最常用的配置方法:

Logger.setLevel():设置日志记录级别
Logger.addHandler()和Logger.removeHandler():为logger对象添加或删除handler处理器对象。
Logger.addFilter()和Logger.removeFilter():为为logger对象添加或删除filter过滤器对象。
配置好logger对象后,就可以使用下面的方法创建日志消息了:
Logger.debug(), Logger.info(), Logger.warning(), Logger.error(), and Logger.critical():创建对应级别的日志,但不一定会被记录。Logger.exception():创建一个类似Logger.error()的日志消息。不同的是Logger.exception()保存有一个追踪栈。该方法只能在异常handler中调用。
Logger.log():显式的创建一条日志,是前面几种方法的通用方法。
注意,getLogger()方法返回一个logger对象的引用,并以你提供的name参数命名,如果未提供名字,那么默认为‘root’。使用同样的name参数,多次调用getLogger(),将返回同样的logger对象。

2.3 Handlers处理器

Handlers对象是日志信息的处理器、分发器。它们将日志分发到不同的目的地。比如有时候我们希望将所有的日志都记录在本地文件内,将error及其以上级别的日志发送到标准输出stdout,将critical级别的日志以邮件的方法发送给管理员。这就需要同时有三个独立的handler,分别负责一个方向的日志处理。
logging模块使用较多的handlers有两个,StreamHandler和FileHandler。

StreamHandler

标准输出stdout(如显示器)分发器。

创建方法: sh = logging.StreamHandler(stream=None)

FileHandler
将日志保存到磁盘文件的处理器。
创建方法: fh = logging.FileHandler(filename, mode=‘a’, encoding=None, delay=False)
handlers对象有下面的方法:
setLevel():和logger对象的一样,设置日志记录级别。那为什么要设置两层日志级别呢?logger对象的日志级别是全局性的,对所有handler都有效,相当于默认等级。而handlers的日志级别只对自己接收到的logger传来的日志有效,进行了更深一层的过滤。setFormatter():设置当前handler对象使用的消息格式。
addFilter() 和 removeFilter():配置或删除一个filter过滤对象
logging模块内置了下面的handler处理器,从字面上你就能看出它们的大概用途:

  • StreamHandler
  • FileHandler
  • BaseRotatingHandler
  • RotatingFileHandler
  • TimedRotatingFileHandler
  • SocketHandler
  • DatagramHandler
  • SMTPHandler
  • SysLogHandler
  • NTEventLogHandler
  • HTTPHandler
  • WatchedFileHandler
  • QueueHandler
  • NullHandler

2.4 Formatters

Formatter对象用来最终设置日志信息的顺序、结构和内容。其构造方法为:

ft = logging.Formatter.__init__(fmt=None, datefmt=None, style=%)

如果不指定datefmt,那么它默认是%Y-%m-%d %H:%M:%S样式的。

style参数默认为百分符%,这表示前面的fmt参数应该是一个%()s格式的字符串,而可以使用的logging内置的keys,如下表所示:

属性格式描述
asctime%(asctime)s日志产生的时间,默认格式为2003-07-08 16:49:45,896
created%(created)ftime.time()生成的日志创建时间戳
filename%(filename)s生成日志的程序名
funcName%(funcName)s调用日志的函数名
levelname%(levelname)s日志级别 (‘DEBUG’, ‘INFO’, ‘WARNING’, ‘ERROR’, ‘CRITICAL’)
levelno%(levelno)s日志级别对应的数值
lineno%(lineno)d日志所针对的代码行号(如果可用的话)
module%(module)s生成日志的模块名
msecs%(msecs)d日志生成时间的毫秒部分
message%(message)s具体的日志信息
name%(name)s日志调用者
pathname%(pathname)s生成日志的文件的完整路径
process%(process)d生成日志的进程ID(如果可用)
processName%(processName)s进程名(如果可用)
thread%(thread)d生成日志的线程ID(如果可用)
threadName%(threadName)s线程名(如果可用)

2.5 Filter过滤器

Handlers和Loggers可以使用Filters来完成比日志级别更复杂的过滤。比如我们定义了filter = logging.Filter(‘a.b.c’),并将这个Filter添加到了一个Handler上,则使用该Handler的Logger中只有名字带a.b.c前缀的Logger才能输出其日志。

创建方法: filter = logging.Filter(name=‘’)

例如:

filter = logging.Filter('mylogger.child1.child2')  
fh.addFilter(filter)

则只会输出下面格式的日志,注意其用户名:

2023-06-12 13:27:46,237 - mylogger.child1.child2 - DEBUG - logger1 debug message
2023-06-12 13:27:46,237 - mylogger.child1.child2 - DEBUG - logger1 debug message
2023-06-12 13:27:46,237 - mylogger.child1.child2 - DEBUG - logger1 debug message
2023-06-12 13:27:46,237 - mylogger.child1.child2 - DEBUG - logger1 debug message

2.6 配置日志模块

有三种配置logging的方法:

创建loggers、handlers和formatters,然后使用Python的代码调用上面介绍过的配置函数。

创建一个logging配置文件,然后使用fileConfig()方法读取它。

创建一个配置信息字典然后将它传递给dictConfig()方法。

下面的例子采用了第一种方法:

#simple_logging_module.py

import logging

# 创建logger记录器
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

# 创建一个控制台处理器,并将日志级别设置为debug。
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# 创建formatter格式化器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 将formatter添加到ch处理器
ch.setFormatter(formatter)

# 将ch添加到logger
logger.addHandler(ch)

# 然后就可以开始使用了!
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

在命令行中运行上面的代码,输出结果如下:

$ python simple_logging_module.py
2023-06-13 13:20:26,967 - simple_example - DEBUG - debug message
2023-06-13 13:20:26,967 - simple_example - INFO - info message
2023-06-13 13:20:26,968 - simple_example - WARNING - warn message
2023-06-13 13:20:26,968 - simple_example - ERROR - error message
2023-06-13 13:20:26,968 - simple_example - CRITICAL - critical message

下面是使用第二种方法,logging配置文件的方式:

# simple_logging_config.py
import logging
import logging.config

logging.config.fileConfig('logging.conf') # 读取config文件

# 创建logger记录器
logger = logging.getLogger('simpleExample')

# 使用日志功能
logger.debug('debug message')
logger.info('info message')
ogger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

其中的logging.conf配置文件内容如下:

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

在命令行中执行代码,结果如下:

$ python simple_logging_config.py
2023-06-13 13:32:55,072 - simpleExample - DEBUG - debug message
2023-06-13 13:32:55,073 - simpleExample - INFO - info message
2023-06-13 13:32:55,073 - simpleExample - WARNING - warn message
2023-06-13 13:32:55,073 - simpleExample - ERROR - error message
2023-06-13 13:32:55,073 - simpleExample - CRITICAL - critical message

Python官方更推荐第三种新的配置方法,类字典形式的配置信息,因为Python的字典运用形式多样,操作灵活。比如,你可以通过JSON格式保存字典,或者YAML格式保存信息,然后读取成字典。当然,你也可以直接在Python代码里编写传统的带有配置信息的字典。一切都是基于键值对形式的就OK。

下面的例子就是基于YAML配置文件的日志。logging.conf.yaml配置文件内容如下:

version: 1
formatters:  
	simple:    
		format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:  
	console:    
		class: logging.StreamHandler    
		level: DEBUG    
		formatter: simple    
		stream: ext://sys.stdout
loggers:  
	simpleExample:    
		level: DEBUG    
		handlers: [console]    
		propagate: no
root:  
	level: DEBUG 
	handlers: [console]

这里要先通过pip安装yaml模块:

pip install pyyaml

yaml模块的使用很简单,使用open()方法打开一个yaml文件对象,然后使用yaml的load()方法将文件内容读成一个Python的字典对象。最后我们根据这个字典对象,使用logging.conf的dictConfig()方法,获取配置信息。如下代码所示:

import logging
import logging.config
import yaml

# 通过yaml文件配置logging
f = open("logging.conf.yaml")
dic = yaml.load(f)
f.close()
logging.config.dictConfig(dic)

# 创建logger
logger = logging.getLogger('simpleExample')

# 输出日志
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

输出结果:

2023-06-13 14:41:09,232 - simpleExample - DEBUG - debug message
2023-06-13 14:41:09,232 - simpleExample - INFO - info message
2023-06-13 14:41:09,232 - simpleExample - WARNING - warn message
2023-06-13 14:41:09,232 - simpleExample - ERROR - error message
2023-06-13 14:41:09,232 - simpleExample - CRITICAL - critical message
输出日志
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')

输出结果:

2023-06-13 14:41:09,232 - simpleExample - DEBUG - debug message
2023-06-13 14:41:09,232 - simpleExample - INFO - info message
2023-06-13 14:41:09,232 - simpleExample - WARNING - warn message
2023-06-13 14:41:09,232 - simpleExample - ERROR - error message
2023-06-13 14:41:09,232 - simpleExample - CRITICAL - critical message

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/641826.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python爬虫——怎么抓取职位信息

目录 背景 为什么要抓取职位信息 怎么抓取职位信息 代码示例 被反爬怎么办 使用代理IP进行爬取 总结 背景 高考刚结束,马上又到了大学生毕业的时候了,各大厂也开始了一波招工潮了,想知道大厂或竞争对手都招些什么人,有什么…

来了解一下这几个网络设备日志级别分别都适用在何种场景?

在华为设备中,涉及到日志的,我们经常会在日志级别上迷糊,本文就给大家介绍8种日志级别以及每个级别适用的场景。 1. Emergency(紧急) 紧急级别的日志是指最高级别的日志,表示系统遇到了严重的错误或故障&…

JMeter+Ant+jenkins搭建接口自动化测试环境

目录 前言: 1.ant简介 2. 构建ant环境 3.JMeter与Ant集成 4. 报告优化 5.jenkins持续集成 前言: JMeter是一个开源的性能测试工具,可以用于测试Web应用程序或API接口的性能,支持多种通信协议和数据格式。Ant是一个构建工具&…

ui自动化 SeleniumBase

目录 前言: git克隆 校验邮件的案例: 注意事项: 前言: SeleniumBase是一个基于Selenium WebDriver的Python框架,用于UI自动化测试。它具有简单易用的API接口,可轻松编写测试脚本以及管理测试用例。SeleniumBase不仅提供了Web…

【LeetCode】HOT 100(10)

题单介绍: 精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。 目录 题单介绍&#…

5月总共面试31次,我人麻了....

3年测试经验原来什么都不是,只是给你的简历上画了一笔,一直觉得经验多,无论在哪都能找到满意的工作,但是现实却是给我打了一个大巴掌!事后也不会给糖的那种... 先说一下自己的个人情况,普通二本计算机专业…

华为OD机试真题 JavaScript 实现【寻找密码】【2023Q1 100分】,附详细解题思路

一、题目描述 小王在进行游戏大闯关,有一个关卡需要输入一个密码才能通过,密码获得的条件如下: 在一个密码本中,每一页都有一个由 26 个小写字母组成的若干位密码,从它的末尾开始依次去掉一位得到的新密码也在密码本…

母线保护(4)

4、母联死区保护 在各种母差保护中,存在一个共同的问题,就是死区问题。 如图,在母联合位时,当故障发生在母联断路器与母联CT之间时,故障电流由II母流向I母,I母小差有差流,判断为I母故障&#x…

yum安装nginx

Nginx介绍 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上Nginx的并发能力确实在同类型的网页服务器中表现较好&…

电脑提示由于找不到vcomp140.dll无法继续执行代码怎么修复呢?这个三个方法可以帮到你

在我们打开游戏或者获取软件的时候,点击电脑提示由于找不到vcomp140.dll无法继续执行代码需要怎么办呢?vcomp140.dll是什么呢?相信困扰着不少小伙伴,vcomp140.dll是Microsoft Visual C Redistributable中的一个动态链接库文件&…

牛客网Java面试题及答案整理(2023年秋招最新版,持续更新)

学习如逆水行舟,尤其是 IT 行业有着日新月异的节奏,我们更要抓紧每一次可以学习和进步的机会。所以,没有撤退可言。 即使是面试跳槽,那也是一个学习的过程。只有全面的复习,才能让我们更好的充实自己,武装…

基于Java高校专业信息管理系统设计与实现(源码+lw+部署文档+讲解等)

博主介绍: ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精…

Spring Security--会话管理

就像登录qq一样,一个手机登录会将另外一个手机挤下线,这个就叫会话管理。 这个东西非常简单,在默认情况下可以登录n多次,一旦开启,就不允许登录多个。 什么是一个会话。 我们简单理解就是一个浏览器的同一个用户算一…

Redux 异步解决方案2. Redux-Saga中间件

利用Generator特性实现异步 因为Generator。结合yield yield操作符会获取右边表达示的值返回 可以用于异步变同步操作 中间件的特性: 以前的 action -> reducers -> store 现在的 action -> middleware -> reducers -> store 注意: reducer的type…

群晖云同步失败?一直卡在连接中怎么办?

群晖云同步是群晖NAS的一款基于网络的数据备份和同步服务,它可以帮助我们在不同设备之间轻松地同步文件、照片、文档等,并且支持自动化执行同步备份任务,让您的数据存储更加安全。 虽然群晖云同步能给我们带来很多便利,但是在…

yolov5 6.1 关于 tensorrt 加速的使用以及问题说明

文章目录 1. 参考连接2. 使用说明2.1 导出加速模型2.1 使用加速模型2.2 加速参数对比 3. 问题说明3.1 在 Tensorrt 8.4.1.5 版本上使用 export.py 导出失败的问题3.2 把模型文件由 best.pt 更换成加速后的 best.engine 后,执行推理时标注的类别名不正确的问题3.3 导…

面向教育机构的IT管理

多年来,高等教育见证了一些惊人的技术创新,包括远程学习、VR 和 AR 实验室、物联网等。随着技术席卷高等教育领域,机构有望高度依赖其技术基础设施,将学生的想法变为现实,以支持学习渠道并促进研究和合作。 另一方面&…

JMeter发送表单数据,响应体报错:参数校验异常

请求方式是post,请求参数就是表单形式。这个时候我们可以把请求参数写到参数里,也可以选择写到消息体数据里。 1、如果是写到参数中,那Content-Type默认就是表单格式,不需要格外添加HTTP信息头管理器。 2、如果是写到消息体数据中…

语音消息实现(聊天向)

语音消息实现记录下: SpringBootVue3客服项目,网页录制发送语音消息 Vue中使用js-audio-recorder插件实现录音功能并实现上传Blob数据到SpringBoot后台接口 2fps/recorder github地址 Recorder的API 语音测试地址 [Web] 4分钟搭建一个简洁好看的 We…

如何购买北京法拍房

1、对于有限购的法拍房来说,在没有购房者资格的前提下,请不要跟拍,就算是房子拍下来了,没办法过户的话,房子还不能算是你的,弃权则被罚保证金。2、对于没有限购的法拍房来说,在没有购房资格的前…