日志(logging模块)
1. 为什么要使用日志(作用)
在学习过程中,写一个小程序或小demo时,遇到程序出错时,我们一般会将一些信息打印到控制台进行查看,方便排查错误。这种方法在较小的程序中很实用,但是当你的程序变大,或是说在实际的工程项目中,代码量都是很大的,代码量一大,不可控因素就多,再将信息打印到控制台进行查看是非常不方便的,此时就需要使用日志来记录程序运行过程中的相关信息,监控程序的运行情况。
2. 基础概念
我们在程序中会使用print打印一些信息以供我们判断程序的运行情况,什么时候需要使用print打印一些信息以及在什么位置使用print,这些都是根据程序自身以及个人的经验。使用日志和使用print是相似的,不同的时,日志具有多种形式来记录一些信息,例如 logging.FileHandler ****将日志信息文件写入文件,logging.handlers.SMTPHandler 将日志信息通过SMTP发送到一个电子邮件地址。
记录和处理日志信息的方式有很多种,logging库中提供了许多方法:https://docs.python.org/zh-cn/3/library/logging.handlers.html# 本文只记录 StreamHandler和 FileHandler 的使用方法。
logging库虽然提供了多种方法来记录和处理日志信息,但并不是什么信息都需要记录的,我们往往会根据程序中各个模块的重要程度来决定是否需要记录信息以及记录哪些信息。logging库根据事件的重要性提供了以下几个级别:
| 级别 | 使用时机 |
|---|---|
| DEBUG | 细节信息,仅当诊断问题时适用。 |
| INFO | 确认程序按预期运行,和print使用类似。 |
| WARNING | 表明有已经或即将发生的意外(例如:磁盘空间不足,数值运算产生精度丢失等)。程序仍按预期进行。 |
| ERROR | 由于严重的问题,程序的某些功能已经不能正常执行。 |
| CRITICAL | 严重的错误,表明程序已不能继续执行。 |
级别大小:DEBUG < INFO < WARNING <ERROR < CRITICAL
划分处理等级的目的是为了针对不同的情况来记录有用的信息,方便有效地监控程序的运行状况,当程序出错时也能方便的定位到。因此在使用logging库记录和处理日志信息前,需要先设定处理等级,默认的等级为 WARNING,当记录和处理日志信息时,只处理大于等于该等级的日志信息。
3. logging库的一些简单使用案例
3.1 像print一样打印日志信息
使用debug()、info()、warning()、error()、critical() 方法分别打印对应的级别及以上的信息,因为默认的级别为 WARNING,所以只会对warning()、error()、critical() 中的信息进行打印。
import logging
if __name__ == "__main__":
logging.debug("the message of debug")
logging.info("the message of debug")
logging.warning("the message of warning")
logging.error("the message of error")
logging.critical("the message of critical")
输出结果:
WARNING:root:the message of warning
ERROR:root:the message of error
CRITICAL:root:the message of critical
3.2 设置级别
使用 basicConfig() 方法设置级别,传入关键字参数 level ,参数值为对应级别的字符串形式。
import logging
if __name__ =="__main__":
logging.basicConfig(level='DEBUG')
logging.debug("the message of debug")
logging.info("the message of debug")
logging.warning("the message of warning")
logging.error("the message of error")
logging.critical("the message of critical")
输出结果:
DEBUG:root:the message of debug
INFO:root:the message of debug
WARNING:root:the message of warning
ERROR:root:the message of error
CRITICAL:root:the message of critical
3.3 在日志中打印变量信息
默认使用 printf 风格的方式进行字符串格式化。
import logging
if __name__ == "__main__":
name = "张三"
age = 24
logging.warning("%s的年龄为%s岁", name, age)
# 也可以使用format的方式进行字符串格式化
logging.warning("{}的年龄为{}岁".format(name, age))
输出结果:
WARNING:root:张三的年龄为24岁
3.4 更改日志信息显示的格式
对于可以出现在格式字符串中的全部内容,可以参考官方文档 LogRecord 属性 。
我们可以将日志信息的显示格式使用关键字 format 设置为:
format='%(asctime)s: %(name)s: %(levelname)s: %(filename)s: %(funcName)s: %(message)s'
记录时间 - 记录器的名称 - 事件等级 - 产生日志信息的源文件名 - 所在函数名 - 提示信息
import logging
def main():
logging.basicConfig(format='%(asctime)s: %(name)s: %(levelname)s: %(filename)s: %(funcName)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')
if __name__ == "__main__":
main()
输出结果:
2022-04-19 15:30:02,404: root: DEBUG: logging_demo.py: main: This message should appear on the console
2022-04-19 15:30:02,404: root: INFO: logging_demo.py: main: So should this
2022-04-19 15:30:02,404: root: WARNING: logging_demo.py: main: And this, too
3.5 将日志信息写入文件
指定文件名 filename,文件写入方式 filenmode,默认写入方式为 a ;
import logging
def main():
fmt = '%(asctime)s: %(name)s: %(levelname)s: %(filename)s: %(funcName)s: %(message)s'
logging.basicConfig(filename="example.log", filemode='w', format=fmt, level="DEBUG")
logging.debug('This message should appear on the console')
logging.info('So should this')
logging.warning('And this, too')
if __name__ == "__main__":
main()
3.6 basicConfig
前面几个案例都使用到了 basicConfig 方法对打印和记录日志信息的行为进行设置,可以设置是将信息显示在控制台还是记录到文件中,可以设置显示或记录的内容格式,设置事件等级等,更详细的设置官方文档已经给出了很细致的解释。
4. 进一步使用
当程序规模变大,使用上面方式介绍的记录日志的方式就会显得捉襟见肘。下面介绍 logging库的进阶使用方式。
logging 库采用模块化的方式来记录日志信息,由以下四个核心组件组成:
Logger(记录器):根据记录器设置的等级捕获日志信息,并传递给对应的处理器;
Handler(处理器):将记录器传递过来的日志信息交给不同的处理器处理;
Filter(过滤器):更细粒度地控制要输出哪些日志记录;
Formatter(格式器):设置日志记录的输出格式;
下面说明这几个组件之间的联系及处理顺序:
- 首先通过
getLogger()方法一个指定名称的 Logger实例的引用,如果没提供名称,则返回root;logger = getLogger(name) - 为 Logger 实例设置捕获信息的等级,默认等级为 WARNING,
logger.setLevel('INFO') logger通过调用debug()、info()、warning()、error()、critical()这些方法来捕获日志信息;Logger只暴露接口供程序员调用,用来捕获日志信息,而不处理信息;只捕获大于等于其自身等级的信息;- 如果 logger 捕获了日志信息,则将日志信息传递给 Handler 进行处理;
- 每个 logger 可以有多个 Handler 处理捕获的日志信息,常用的 StreamHandler 和 FileHandler ,StreamHandler 将日志信息打印到终端显示,FileHandler 将日志信息记录写入到文件中;不同的Handler 也都具有等级属性,每个Handler 只会处理大于等于自身等级的日志信息;
其中 Filter 可以作用 Logger 和 Handler,用于更细粒度地控制捕获或输出哪些日志信息,本文不讨论 Filter 使用。
日志事件信息流程如下图所示:

整体代码框架如下:
# 实例化一个 Logger 对象,并记录一个名字
# 在命名记录器时使用的一个好习惯,是在每个使用日志记录的模块中使用模块级记录器
logger = logging.getLogger(__name__)
# 设置记录器捕获日志信息的等级
logger.setLevel("INFO")
# 实例化处理器对象
ch = logging.StreamHandler()
fh = logging.FileHandler("example.log")
# 设置处理器处理信息的等级
ch.setLevel("INFO")
fh.setLevel("WARNING")
# 设置处理器输出日志信息的格式
fmt = logging.Formatter('%(asctime)s: %(levelname)s: %(name)s: %(filename)s: %(message)s')
ch.setFormatter(fmt)
fh.setFormatter(fmt)
# 给记录器添加处理器
logger.addHandler(ch)
logger.addHandler(fh)
# 捕获日志信息
logger.info("the message info")
logger.error("the message of error")
将上面代码封装成一个类,方便使用
import logging
class Logger:
"""
将日志信息打印到控制台和记录到文件的操作封装成一个类
"""
def __init__(self, name: str, console_handler_level: str = logging.DEBUG,
fmt: str = '%(asctime)s: %(levelname)s: %(name)s: %(filename)s: %(message)s'):
"""
默认会添加一个等级为 'DEBUG' 的 Handler 对象到 Logger 对象
:param name: handler 的名称
:param console_handler_level: 设置 StreamHandler 的等级
:param fmt: 日志消息的显示格式
"""
self.logger = logging.getLogger(name)
self.logger.setLevel(logging.DEBUG)
self.fmt = logging.Formatter(fmt)
self.set_console_handler(console_handler_level)
def set_console_handler(self, console_handler_level: str = logging.DEBUG) -> None:
ch = logging.StreamHandler()
ch.setLevel(console_handler_level)
ch.setFormatter(self.fmt)
self.logger.addHandler(ch)
def set_file_handler(self, filename: str, mode: str = 'a', file_handler_level: str = logging.INFO) -> None:
fh = logging.FileHandler(filename, mode=mode, encoding='utf-8')
fh.setLevel(file_handler_level)
fh.setFormatter(self.fmt)
self.logger.addHandler(fh)
def debug(self, msg):
self.logger.debug(msg)
def info(self, msg):
self.logger.info(msg)
def warning(self, msg):
self.logger.warning(msg)
def error(self, msg):
self.logger.error(msg)
def critical(self, msg):
self.logger.critical(msg)
日志(logging模块)的更多相关文章
- day18包的使用与日志(logging)模块
包的使用与日志(logging)模块1. 什么是包 包就是一个包含有__init__.py文件的文件夹 包本质就是一种模块,即包是用包导入使用的,包内部包含的文件也都是用来被导入使用2 为 ...
- python中日志logging模块的性能及多进程详解
python中日志logging模块的性能及多进程详解 使用Python来写后台任务时,时常需要使用输出日志来记录程序运行的状态,并在发生错误时将错误的详细信息保存下来,以别调试和分析.Python的 ...
- python 的日志logging模块学习
1.简单的将日志打印到屏幕 import logging logging.debug('This is debug message') logging.info('This is info messa ...
- Python之日志 logging模块
关于logging模块的日志功能 典型的日志记录的步骤是这样的: 创建logger 创建handler 定义formatter 给handler添加formatter 给logger添加handler ...
- python 的日志logging模块
1.简单的将日志打印到屏幕 import logging logging.debug('This is debug message')logging.info('This is info messag ...
- Python日志(logging)模块,shelve,sys模块
菜鸟学python第十七天 1.logging 模块 logging模块即日志记录模块 用途:用来记录日志 为什么要记录日志: 为了日后复查,提取有用信息 如何记录文件 直接打开文件,往里写东西 直接 ...
- python的日志logging模块性能以及多进程
写在前面: 日志是记录操作的一种好方式.但是日志,基本都是基于文件的,也就是要写到磁盘上的.这时候,磁盘将会成为一个性能瓶颈.对于普通的服务器硬盘(机械磁盘,非固态硬盘),python日志的性能瓶颈是 ...
- python+Appium自动化:日志logging模块
日志级别 debug.info.warn.error.critical五个级别 logging模块构成(四部分) logger(记录器,用于日志采集) Handler(处理器,将日志记录发送到合适的路 ...
- Python中日志logging模块
# coding:utf-8 import logging import os import time class Logger(object): def __init__(self): # 创建一个 ...
- Python的日志记录-logging模块的使用
一.日志 1.1什么是日志 日志是跟踪软件运行时所发生的事件的一种方法,软件开发者在代码中调用日志函数,表明发生了特定的事件,事件由描述性消息描述,同时还包含事件的重要性,重要性也称为级别或严重性. ...
随机推荐
- 运维:ITSM
IT服务管理(ITSM)是一套帮助企业对IT系统的规划.研发.实施和运营进行有效管理的方法,是一套方法论.ITSM起源于ITIL(IT Infrastructure Library,IT基础架构标准库 ...
- 872. Leaf-Similar Trees - LeetCode
Question 872. Leaf-Similar Trees Solution 题目大意: 如果两个二叉树的叶子节点相同就认为这两个二叉树相似.给两个二叉树判断是否相似. 思路: 用递归把两个二叉 ...
- Cocos---监听、触摸事件、坐标系转换
监听.触摸事件.坐标系转换 Creator的系统事件 分为"节点系统事件"和"全局系统事件". 节点系统事件:触发在节点上,包括鼠标事件和触摸事件. 全局系统事 ...
- Meaven静态资源过滤
` 点击查看代码 <build> <resources> <resource> <directory>src/main/java</directo ...
- README.exe 是的,你看错是EXE
SmartIDE让你的README变成可执行文档,再也不用编写无用的文档,再也不必操心环境问题. 作为开发者,拿到一个新的代码库的时候一般都会先去看README文件,通过这个文件可以知道这套代码所 ...
- 创建NuGet本地包源
NuGet 是免费.开源的包管理开发工具,专注于在 .NET 应用开发过程中,简单地合并第三方的组件库.使用Visual Studio 可以很方便地将类库等项目打包发布,最简单的办法是上传到Nuget ...
- 基于bat脚本的前端发布流程设计与实现
写在前面 本文大致向读者介绍了楼下几点知识,希望在编写bat脚本时候能够帮到读者,如果能够有所启迪,那就更好了. bat脚本的相关知识和案例编写 用windows自带的命令压缩文件 windows和l ...
- 内网 Ubuntu 20.04 搭建 docusaurus 项目(或前端项目)的环境(mobaxterm、tigervnc、nfs、node)
内网 Ubuntu 20.04 搭建 docusaurus 项目(或前端项目)的环境 背景 内网开发机是 win7,只能安装 node 14 以下,而 spug 的文档项目采用的是 Facebook ...
- JS:条件语句3
1.while while 语句只要指定条件为 true,就会执行循环. 语法: while(条件){ 语句: } 例: var i = 0; while (i < 5) { console.l ...
- SAP Tree
Effect picture Code as bellow *&---------------------------------------------------------------- ...