python-28-日志模块Loguru的应用

news2024/12/26 11:48:01

参考为什么不推荐使用Python原生日志库?
参考loguru,一个神奇的 python 库
Loguru 是一个旨在为 Python 带来愉快的日志记录的库,它可以完全增强你的日志记录体验,并且非常易于使用。
对logging及Loguru进行使用对比。

1 Loguru的使用

1.1 将调试日志输出到终端

from loguru import logger
logger.debug("That's it, beautiful and simple logging!")

1.2 将日志输出到文件中

from loguru import logger
logger.add("file_{time}.log")
logger.debug("That's it, beautiful and simple logging!")

这将在当前运行的文件夹中生成 file_current time.log 的日志文件。
同时如果在IDE中执行,终端也会输出日志信息。

1.3 按时间滚动日志

要按时间滚动,只需要在 logger.add 参数中添加一个 rotation 参数即可。

from loguru import logger
# Create new file at 12AM
logger.add("file_2.log", rotation="12:00") 
logger.debug("That's it, beautiful and simple logging!")

这样,如果当前时间超过了这个设定的时间,就会生成一个新的日志文件。如果没有,请使用原始日志文件。

1.4 按大小滚动日志

from loguru import logger
logger.add("file_1.log", rotation="1 MB")
logger.debug("That's it, beautiful and simple logging!")

这样,一旦日志文件大小超过1MB,就会生成一个新的日志文件。

1.5 压缩日志

如果你不想删除原来的日志文件,Loguru 还支持直接压缩日志。

from loguru import logger
logger.add("file_2.log", compression="zip")

会直接将该日志文件压缩为zip。

1.6 定制颜色

Loguru 支持自定义颜色,如果你不喜欢它的默认颜色,你可以这样更改。

from loguru import logger
import sys
logger.add(sys.stdout,
           colorize=True,
           format="<black>{time}</black> <level>{message}</level>")
logger.debug("That's it, beautiful and simple logging!")

1.7 多进程安全

Loguru 默认是线程安全的,但它不是多进程安全的。
但如果你需要多进程/异步日志记录,它也支持,只需添加一个 enqueue 参数即可。
在config中配置全局的logger,这样主程序和子程序都会写入同一个日志文件中。
一、config.py

from loguru import logger
logger.add("file.log",enqueue=True)

二、main.py

from multiprocessing import Process
import os
from config import logger
from demo import fun
if __name__ == '__main__':
    # p进程执行fun函数
    p1 = Process(target=fun)
    p1.start()  # 进程开始
    logger.info("PID={},This is mainFun results".format(os.getpid()))
    p2 = Process(target=fun)
    p2.start()  # 进程开始

三、demo.py

import time
from config import logger
import os
def fun():
    count = 0
    while count < 30:
        logger.error("PID={},error message".format(os.getpid()))
        time.sleep(20)
        count = count + 1

2 logging与Loguru对比

2.1 快速示例

(1)在logging中,默认的日志功能输出的信息较为有限。
(2)看看loguru,默认生成的信息就较为丰富了,提供了执行时间、等级、在哪个函数调用、具体哪一行等信息。

2.1.1 logging

import logging

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")

if __name__ == "__main__":
    main()

输出如下:

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

2.1.2 Loguru

from loguru import logger

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()

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

2. 2 格式化日志

(1)在logging中使用%达到格式化目的。
(2)loguru使用和f-string相同的{}格式,更方便。

2.2.1 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")

if __name__ == "__main__":
    main()

在这里插入图片描述

2.2.2 Loguru

from loguru import logger
import sys
logger.add(
    sys.stdout,
    level="INFO",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function}:{line} - {message}",
)
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()

控制台输出自定义格式的内容。
同时控制台输出默认格式的内容。
在这里插入图片描述

2.3 日志保存

(1)在logging中,实现日志保存与日志打印需要两个额外的类,FileHandler 和 StreamHandler。
(2)在loguru中,只需要使用add方法即可达到目的。

2.3.1 logging

import logging

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",
    handlers=[
        logging.FileHandler(filename="info.log"),
        logging.StreamHandler(),
    ],
)

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()

在这里插入图片描述

2.3.2 Loguru

from loguru import logger

logger.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()

控制台会继续按debug级别输出。
日志文件中按info输出。
在这里插入图片描述

2.4 日志轮换

日志轮换指通过定期创建新的日志文件并归档或删除旧的日志来防止日志变得过大。
(1)在logging中,需要一个名为 TimedRotatingFileHandler 的附加类。
(2)在loguru中,可以通过将 rotation 和 retention 参数添加到 add 方法来达到目的。

2.4.1 logging

以下代码示例代表每周切换到一个新的日志文件 ( when=“S”, interval=10 ),并保留最多 4个日志文件 ( backupCount=4 )

import logging
from logging.handlers import TimedRotatingFileHandler

logger = 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="S", interval=10, 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()

2.4.2 Loguru

from loguru import logger

logger.add("debug.log", level="INFO", rotation="10 seconds", retention="40 seconds")


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()

2.5 日志筛选log filter

日志筛选指根据特定条件有选择的控制应输出与保存哪些日志信息。
(1)在logging中,实现该功能需要创建自定义日志过滤器类。
(2)在loguru中,可以简单地使用lambda函数来过滤日志。

2.5.1 logging

import logging


logging.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 "my concern message" 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("my concern message")
    logger.info("Ha Ha")
    logger.info("my concern message continue")


if __name__ == "__main__":
    main()

2.5.2 Loguru

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

from loguru import logger

logger.add("test.log",
           filter=lambda x: "Cai Xukong" in x["message"],
           level="INFO")


def main():
    logger.info("my concern message")
    logger.info("Ha Ha")
    logger.info("my concern message continue")


if __name__ == "__main__":
    main()

2.6 捕获异常catching exception

(1)在logging中捕获异常较为不便且难以调试。
(2)在loguru中,通过显示包含变量值的完整堆栈跟踪来方便用户识别。

2.6.1 logging

import logging

logging.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 / b


def nested(num):
    try:
        division(1, num)
    except ZeroDivisionError:
        logging.exception("ZeroDivisionError")


if __name__ == "__main__":
    nested(0)

输出如下:下面输出的信息未提供触发异常的num值信息。
在这里插入图片描述

2.6.2 Loguru

from loguru import logger


def division(a, b):
    return a / b

def nested(num):
    try:
        division(1, num)
    except ZeroDivisionError:
        logger.exception("ZeroDivisionError")


if __name__ == "__main__":
    nested(0)

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

from loguru import logger


def division(a, b):
    return a / b


@logger.catch
def nested(num):
    division(1, num)


if __name__ == "__main__":
    nested(0)

在这里插入图片描述

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

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

相关文章

L4级自动驾驶前装量产车型来了,小马智行与丰田联合打造

11月5日&#xff0c;小马智行与丰田汽车联合发布的首款纯电自动驾驶出租车&#xff08;Robotaxi&#xff09;概念车在第六届进博会亮相&#xff0c;该车型基于广汽丰田生产的bZ4X纯电车辆平台打造&#xff0c;将搭载小马智行研发的第七代L4级自动驾驶乘用车软硬件系统。 今年8月…

实测Java批量导入百万级数据

JAVA通过ThreadPoolTaskExecutor批量插入百万级数据 文章目录 JAVA通过ThreadPoolTaskExecutor批量插入百万级数据一、前言二、实现步骤1、application.yml添加线程池配置信息2、业务类&#xff0c;创建多线程批量插入具体业务方法3、spring容器注入线程池bean对象4、测试 三、…

leetcode:13. 罗马数字转整数(python3解法)

难度&#xff1a;简单 罗马数字包含以下七种字符: I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M …

C/S架构的医学影像PACS系统源码,应用于放射、超声、内窥镜、病理等影像科室

C/S架构的PACS系统&#xff0c;采用DICOM3.0国际标准设计&#xff0c;以大型关系型数据库作为数据和图像的存储管理工具&#xff0c;是集医学影像的采集、传输、存储、查询、诊断、报告、综合信息管理等于一体的综合应用系统。 系统主要进行病人信息和影像的获取、处理、存储、…

windows10录屏神器,轻松保存高光时刻

录制电脑屏幕成了人们日常生活中经常需要面对的任务&#xff0c;无论是为了制作教程、保存游戏精彩瞬间&#xff0c;还是为了录制在线会议&#xff0c;一个功能强大、简单易用的录屏软件成为人们的迫切需求。在Windows 10操作系统下&#xff0c;有多种录屏方法可供选择。本文将…

如何查看苹果手机电池健康情况?快速查询方法来了!

使用苹果手机的小伙伴们&#xff0c;你们是否关心自己手机的电池健康状况&#xff1f;想随时掌握电池的使用状态&#xff0c;却不知道在哪里查看&#xff1f;本文将为大家提供有关苹果手机电池健康的简单查询方法&#xff0c;让您能够随时随地轻松掌握手机电池的健康状况。 操作…

sqlite3.NotSupportedError: deterministic=True requires SQLite 3.8.3 or higher

问题描述 sqlite3.NotSupportedError: deterministicTrue requires SQLite 3.8.3 or higher 解决方法 A kind of solution is changing the database from sqlite3 to pysqlite3. After acticate the virtualenv, install pysqlite. pip3 install pysqlite3 pip3 install …

CS免杀姿势

一&#xff1a;环境 1.公网vps一台 2.Cobalt Strike 4.7 3.免杀脚本 二&#xff1a;生成payload 生成一个payload c格式的x64位payload 三&#xff1a;免杀 下载免杀脚本 .c打开是这样的 把双引号里面的内容复制出来&#xff0c;放到脚本目录下的1.txt 运行生成器.…

刹车过电压保护

肖特基漏电流大&#xff0c;电池供电能省则省 最好是RCD缓冲&#xff0c;二极管要用快恢复 可以直接连&#xff0c;隔离可以用光耦或者逻辑门 问题4选的三极管Qg太大 问题九选的mos管Rdson太大 要并快恢复

蓝桥杯每日一题203.11.7

题目描述 题目分析 使用dp思维&#xff0c;当前位置是否可行是有上一位置推来&#xff0c;计算出最大的可行位置即可 #include <stdio.h> #include <string.h>#define N 256 int f(const char* s1, const char* s2) {int a[N][N];int len1 strlen(s1);int len2 …

如何在Python爬虫中使用IP代理以避免反爬虫机制

目录 前言 一、IP代理的使用 1. 什么是IP代理&#xff1f; 2. 如何获取IP代理&#xff1f; 3. 如何使用IP代理&#xff1f; 4. 如何避免IP代理失效&#xff1f; 5. 代理IP的匿名性 二、代码示例 总结 前言 在进行爬虫时&#xff0c;我们很容易会遇到反爬虫机制。网站…

不同对话分支的生成展示

第一个分支 第二个分支 生成过程 苏州有几个区 curl -H content-type: application/json -H Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTk1OTM5MzYsInVzZXJfaWQiOiI2In0.MkYG3nBcR-ROHvARpEfnWiw-Jsplap73qEeDn-L7v8I -d {"model"…

Flutter利用GridView创建网格布局实现优美布局

文章目录 简介使用详解导入依赖项创建一个基本的 GridView一些参数说明使用GridView.count来构造 其他控制总结 简介 GridView 是 Flutter 中用于创建网格布局的强大小部件。它允许你在行和列中排列子小部件&#xff0c;非常适合显示大量项目&#xff0c;例如图像、文本、卡片…

LiveMedia支持海康大华GB28181语音对讲需要的设备及服务准备

1、背景 GB28181支持国标协议的设备&#xff0c;通过GB28181注册接入到国标视频平台后。视频平台在某些情况下需要喊话摄像头&#xff0c;LiveMedia视频监控平台支持这样的国标设备语音对讲。就是可以从控制中心和您关注的设备间&#xff0c;进行语音对讲。 2、准备 2.1、准…

3D打印服务展示预约小程序的效果如何

3D打印服务的需求度非常高&#xff0c;同时还有加工、设计等&#xff0c;很多情况下商家需要推广获客及信息展示&#xff0c;而客户也需要多渠道寻找服务订购或咨询等。而在实际经营&#xff0c;3D打印服务商家也面临多个痛点&#xff1a; 1、品牌宣传拓客难 印刷包装行业除了…

用CHAT写APP的权限需求

今天我们来接触一个关于程序的问题&#xff0c;探索更多知识点 问CHAT&#xff1a;一个nuiapp开发的前端app&#xff0c;一般用户安装的时候&#xff0c;都有什么权限可以获取&#xff1f;有什么权限是牵扯隐私的&#xff1f; NUIApp&#xff08;Native User Interface App&am…

TikTok与老年用户:社交媒体的跨代交流

在数字时代&#xff0c;社交媒体已成为人们沟通、分享和互动的主要平台。然而&#xff0c;社交媒体不再仅仅局限于年轻一代&#xff0c;老年用户也逐渐加入其中。 其中&#xff0c;TikTok是一个引领潮流的短视频社交媒体应用&#xff0c;正在吸引越来越多的老年用户。本文将探…

​​Android平台GB28181历史视音频文件回放规范解读及技术实现

技术背景 在实现GB28181历史视音频文件回放之前&#xff0c;我们已完成了历史视音频文件检索和下载&#xff0c;历史视音频回放&#xff0c;在GB28181平台非常重要&#xff0c;比如执法记录仪等前端设备&#xff0c;默认录像数据存储在前端设备侧&#xff0c;如果需要上传到平…

光模块厂家如何实现千兆和万兆的大规模量产

随着网络需求的不断增长&#xff0c;千兆光模块和万兆光模块成为了网络通信中不可或缺的组件。但是&#xff0c;如何实现这些高速光模块的量产却是厂家们面临的难题。本文将介绍千兆光模块和万兆光模块的生产工艺差异和技术挑战&#xff0c;并探讨厂家如何实现千兆和万兆的大规…

JWT简介 JWT结构 JWT示例 前端添加JWT令牌功能 后端程序

目录 1. JWT简述 1.1 什么是JWT 1.2 为什么使用JWT 1.3 JWT结构 1.4 验证过程 2. JWT示例 2.1 后台程序 2.2 前台加入jwt令牌功能 1. JWT简述 1.1 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准&#xff08;(RFC 7…