为什么不建议使用Python自带的logging?

B站|公众号:啥都会一点的研究生

包括我在内的大多数人,当编写小型脚本时,习惯使用print来debug,肥肠方便,这没问题,但随着代码不断完善,日志功能一定是不可或缺的,极大程度方便问题溯源以及甩锅,也是每个工程师必备技能

Python自带的logging我个人不推介使用,不太Pythonic,而开源的Loguru库成为众多工程师及项目中首选,本期将同时对loggingLoguru进行使用对比,希望有所帮助

插播,更多文字总结·指南·实用工具·科技前沿动态第一时间更新在公粽号【啥都会一点的研究生

快速示例

logging中,默认的日志功能输出的信息较为有限

import logginglogger = logging.getLogger(__name__)def main():logger.debug("This is a debug message")logger.info("This is an info message")logger.warning("This is a warning message")logger.error("This is an error message")if __name__ == "__main__":main()

输出(logging默认日志等级为warning,故此处未输出info与debug等级的信息)

WARNING:root:This is a warning message
ERROR:root:This is an error message

再来看看loguru,默认生成的信息就较为丰富了

from loguru import loggerdef main():logger.debug("This is a debug message")logger.info("This is an info message")logger.warning("This is a warning message")logger.error("This is an error message")if __name__ == "__main__":main()

在这里插入图片描述
提供了执行时间、等级、在哪个函数调用、具体哪一行等信息

格式化日志

格式化日志允许我们向日志添加有用的信息,例如时间戳、日志级别、模块名称、函数名称和行号

logging中使用%达到格式化目的

import logging# Create a logger and set the logging level
logging.basicConfig(level=logging.INFO,format="%(asctime)s | %(levelname)s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",datefmt="%Y-%m-%d %H:%M:%S",
)logger = logging.getLogger(__name__)def main():logger.debug("This is a debug message")logger.info("This is an info message")logger.warning("This is a warning message")logger.error("This is an error message")

输出

2023-10-18 15:47:30 | INFO | tmp:<module>:186 - This is an info message
2023-10-18 15:47:30 | WARNING | tmp:<module>:187 - This is a warning message
2023-10-18 15:47:30 | ERROR | tmp:<module>:188 - This is an error message

loguru使用和f-string相同的{}格式,更方便

from loguru import loggerlogger.add(sys.stdout,level="INFO",format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function}:{line} - {message}",
)

日志保存

logging中,实现日志保存与日志打印需要两个额外的类,FileHandlerStreamHandler

import logginglogging.basicConfig(level=logging.DEBUG,format="%(asctime)s | %(levelname)s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",datefmt="%Y-%m-%d %H:%M:%S",handlers=[logging.FileHandler(filename="/your/save/path/info.log", level=logging.INFO),logging.StreamHandler(level=logging.DEBUG),],
)logger = logging.getLogger(__name__)def main():logging.debug("This is a debug message")logging.info("This is an info message")logging.warning("This is a warning message")logging.error("This is an error message")if __name__ == "__main__":main()

但是在loguru中,只需要使用add方法即可达到目的

from loguru import loggerlogger.add('info.log',format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function}:{line} - {message}",level="INFO",
)def main():logger.debug("This is a debug message")logger.info("This is an info message")logger.warning("This is a warning message")logger.error("This is an error message")if __name__ == "__main__":main()

日志轮换

日志轮换指通过定期创建新的日志文件并归档或删除旧的日志来防止日志变得过大

logging中,需要一个名为 TimedRotatingFileHandler 的附加类,以下代码示例代表每周切换到一个新的日志文件 ( when=“WO”, interval=1 ),并保留最多 4 周的日志文件 ( backupCount=4 )

import logging
from logging.handlers import TimedRotatingFileHandlerlogger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)# Create a formatter with the desired log format
formatter = logging.Formatter("%(asctime)s | %(levelname)-8s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",datefmt="%Y-%m-%d %H:%M:%S",
)file_handler = TimedRotatingFileHandler(filename="debug2.log", when="WO", interval=1, backupCount=4
)
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)def main():logger.debug("This is a debug message")logger.info("This is an info message")logger.warning("This is a warning message")logger.error("This is an error message")if __name__ == "__main__":main()

loguru中,可以通过将 rotationretention 参数添加到 add 方法来达到目的,如下示例,同样肥肠方便

from loguru import loggerlogger.add("debug.log", level="INFO", rotation="1 week", retention="4 weeks")def main():logger.debug("This is a debug message")logger.info("This is an info message")logger.warning("This is a warning message")logger.error("This is an error message")if __name__ == "__main__":main()

日志筛选

日志筛选指根据特定条件有选择的控制应输出与保存哪些日志信息

logging中,实现该功能需要创建自定义日志过滤器类

import logginglogging.basicConfig(filename="test.log",format="%(asctime)s | %(levelname)-8s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",level=logging.INFO,
)class CustomFilter(logging.Filter):def filter(self, record):return "Cai Xukong" in record.msg# Create a custom logging filter
custom_filter = CustomFilter()# Get the root logger and add the custom filter to it
logger = logging.getLogger()
logger.addFilter(custom_filter)def main():logger.info("Hello Cai Xukong")logger.info("Bye Cai Xukong")if __name__ == "__main__":main()

loguru中,可以简单地使用lambda函数来过滤日志

from loguru import loggerlogger.add("test.log", filter=lambda x: "Cai Xukong" in x["message"], level="INFO")def main():logger.info("Hello Cai Xukong")logger.info("Bye Cai Xukong")if __name__ == "__main__":main()

捕获异常

logging中捕获异常较为不便且难以调试,如

import logginglogging.basicConfig(level=logging.DEBUG,format="%(asctime)s | %(levelname)s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",datefmt="%Y-%m-%d %H:%M:%S",
)def division(a, b):return a / bdef nested(c):try:division(1, c)except ZeroDivisionError:logging.exception("ZeroDivisionError")if __name__ == "__main__":nested(0)
Traceback (most recent call last):File "logging_example.py", line 16, in nesteddivision(1, c)File "logging_example.py", line 11, in divisionreturn a / b
ZeroDivisionError: division by zero

上面输出的信息未提供触发异常的c值信息,而在loguru中,通过显示包含变量值的完整堆栈跟踪来方便用户识别

from loguru import loggerdef division(a, b):return a / bdef nested(c):try:division(1, c)except ZeroDivisionError:logger.exception("ZeroDivisionError")if __name__ == "__main__":nested(0)

在这里插入图片描述
值得一提的是,loguru中的catch装饰器允许用户捕获函数内任何错误,且还会标识发生错误的线程

from loguru import loggerdef division(a, b):return a / b@logger.catch
def nested(c):division(1, c)if __name__ == "__main__":nested(0)

在这里插入图片描述

OK,作为普通玩家以上功能足以满足日常日志需求,通过对比loggingloguru应该让大家有了直观感受,哦对了,loguru如何安装?

pip install loguru

以上就是本期的全部内容,期待点赞在看,我是啥都生,下次再见

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023-10-17 LeetCode每日一题(倍数求和)

2023-10-17每日一题 一、题目编号 2652. 倍数求和二、题目链接 点击跳转到题目位置 三、题目描述 给你一个正整数 n &#xff0c;请你计算在 [1&#xff0c;n] 范围内能被 3、5、7 整除的所有整数之和。 返回一个整数&#xff0c;用于表示给定范围内所有满足约束条件的数…

10_集成学习方法:随机森林、Boosting

文章目录 1 集成学习&#xff08;Ensemble Learning)1.1 集成学习1.2 Why need Ensemble Learning?1.3 Bagging方法 2 随机森林(Random Forest)2.1 随机森林的优点2.2 随机森林算法案例2.3 随机森林的思考&#xff08;--->提升学习&#xff09; 3 随机森林&#xff08;RF&a…

经典链表问题:解析链表中的关键挑战

这里写目录标题 公共子节点采用集合或者哈希采用栈拼接两个字符串差和双指针 旋转链表 公共子节点 例如这样一道题&#xff1a;给定两个链表&#xff0c;找出它们的第一个公共节点。 具体的题目描述我们来看看牛客的一道题&#xff1a; 这里我们有四种解决办法&#xff1a; …

跟随光标圆形文本旋转

今天给大家带来的是光标变成圆形字符串环绕 不多说先上效果图 原理呢,也很简单 就是先把文本 <h2>大威天龙 - 世尊地藏 - 般若诸佛 - 般若巴嘛哄 -</h2>然后使用js将文本处理成每个字符一个span,并且让他们旋转 let text document.querySelector(h2)text.innerH…

第 368 场 LeetCode 周赛题解

A 元素和最小的山形三元组 I 前后缀操作&#xff1a;求出前后缀上的最小值数组&#xff0c;然后枚举 j j j class Solution { public:int minimumSum(vector<int> &nums) {int n nums.size();vector<int> l(n), r(n);//l[i]min{nums[0],...,nums[i]}, r[i]mi…

自然语言处理---Self Attention自注意力机制

Self-attention介绍 Self-attention是一种特殊的attention&#xff0c;是应用在transformer中最重要的结构之一。attention机制&#xff0c;它能够帮助找到子序列和全局的attention的关系&#xff0c;也就是找到权重值wi。Self-attention相对于attention的变化&#xff0c;其实…

数字孪生智慧建筑可视化系统,提高施工效率和建造质量

随着科技的不断进步和数字化的快速发展&#xff0c;数字孪生成为了建筑行业的一个重要的概念&#xff0c;被广泛应用于智能化建筑的开发与管理中。数字孪生是将现实世界的实体与数字世界的虚拟模型进行连接和同步&#xff0c;从而实现实时的数据交互和模拟仿真。数字孪生在建筑…

Python数字类型

目录 目标 版本 种类 官方文档 数据运算方法 常用函数 转整数 转浮点数 转绝对值 四舍五入 进制转换 math模块常用函数 目标 掌握Python两种数据类型的使用方法。 版本 Python 3.12.0 种类 数字类型有三种&#xff0c;分别是&#xff1a; 整数&#xff08;int&…

FPGA设计FIR滤波器低通滤波器,代码及视频

名称&#xff1a;FIR滤波器低通滤波器 软件&#xff1a;Quartus 语言&#xff1a;Verilog/VHDL 本资源含有verilog及VHDL两种语言设计的工程&#xff0c;每个工程均可实现以下FIR滤波器的功能。 代码功能&#xff1a; 设计一个8阶FIR滤波器&#xff08;低通滤波器&#xff…

【Axure高保真原型】可视化图表图标

今天和粉丝们免费分享可视化图表图标原型模板&#xff0c;包括柱状图、条形图、环形图、散点图、水波图等常用的可视化图表图标。 【原型效果】 【原型预览】 https://axhub.im/ax9/d402c647c82f9185/#c1 【原型下载】 这个模板可以在 Axure高保真原型哦 小程序里免费下载哦…

设计模式-责任链设计模式

核心思想 客户端发出一个请求&#xff0c;链上的对象都有机会来处理这一请求&#xff0c;而客户端不需要知道谁是具体的处理对象让多个对象都有机会处理请求&#xff0c;避免请求的发送者和接收者之间的耦合关系&#xff0c;将这个对象连成一条调用链&#xff0c;并沿着这条链…

Linux系统管理:虚拟机Kylin OS安装

目录 一、理论 1.Kylin OS 二、实验 1.虚拟机Kylin OS安装准备阶段 2.安装Kylin OS 3.进入系统 一、理论 1.Kylin OS &#xff08;1&#xff09;简介 麒麟操作系统&#xff08;Kylin OS&#xff09;亦称银河麒麟&#xff0c;是由中国国防科技大学、中软公司、联想公司…