Python 日志记录-loguru
Python 日志记录-loguru
使用logging模块时
用python写代码时,logging模块最基本的几行配置,如下:
import logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) logger.info('this is another debug message') logger.warning('this is another debug message') logger.error('this is another debug message') logger.info('this is another debug message')
执行结果如下:
引言 loguru
如果想更简洁,可用loguru库
loguru默认的输出格式是上面的内容,有时间、级别、模块名、行号以及日志信息,不需要手动创建 logger,直接使用即可,另外其输出还是彩色的,看起来会更加友好。
官方文档
安装
pip install loguru 1
日志级别
Level name | Severity value | Logger method |
---|---|---|
TRACE | 5 | logger.trace |
DEBUG | 10 | logger.debug |
INFO | 20 | logger.info |
SUCCESS | 25 | logger.success |
WARNING | 30 | logger.warning |
ERROR | 40 | logger.error |
CRITICAL | 50 | logger.critical |
简单测试下
from loguru import logger logger.debug("debug") logger.info("info") logger.success("success") logger.warning("warning") logger.error("error") logger.critical("critical") 12345678
输出结果
logger.add() #参数: sys.stdout-在控制台输出,如果不想在控制台输出,直接写文件名即可 ../haha.log level:日志的级别。 debug,info,warning,error encoding='utf-8' 如果输出日志到文件中时,需要指定此参数 format:日志的输出格式'[{time}][{level}][{file}:line{line}:function_name:{function}] || mesg = {message}' enqueue:什么方式写日志 True为异步,false为同步 rotation:超过多少就生成一个新的日志文件,可设置大小 retention:多长时间后会删除以前产生的日志,当前的日志不会受影响
特性
简介
此函数应用于注册接收器,这些接收器负责管理使用记录字典上下文化的日志消息。接收器可以采用多种形式:简单函数、字符串路径、类似文件的对象、协程函数或内置处理程序。
请注意:可以使用remove()函数来删除以前添加的处理程序。
例子:
import sys from loguru import logger logger.add("test.log", format="{time} {level} {message}", filter="", level="INFO", encoding="utf-8") logger.debug("debug") logger.info("info") logger.success("success") logger.warning("warning") logger.error("error") logger.critical("critical") 1234567891011
效果,输出日志到test.log文件
2022-07-27T17:14:36.393072+0800 INFO info 2022-07-27T17:14:36.394068+0800 SUCCESS success 2022-07-27T17:14:36.395066+0800 WARNING warning 2022-07-27T17:14:36.396063+0800 ERROR error 2022-07-27T17:14:36.397060+0800 CRITICAL critical 12345
rotation/retension/compression
官方介绍:loguru.logger — loguru documentation
rotation:指示何时应关闭当前记录的文件并创建新文件,可以是文件大小/每天的时间点/时间间隔等。
logger.add("test1.log", rotation="500 MB") # 日志文件超过500M创建新的文件 logger.add("test2.log", rotation="12:00") # 每天中午12点创建新的日志文件 logger.add("test3.log", rotation="1 week") # 当前使用的日志文件超过1周,创建新的日志文件 123
retension:指示合适应该删除旧文件。
logger.add("test4.log", retention="10 days") # 超过十天的日志文件删除 1
compression:日志文件在关闭时应转换为的压缩或归档格式。
logger.add("test5.log", compression="zip") # 日志文件关闭后,使用zip进行压缩 1
50m一个文件,保留3个文件 logger.add('sync_inc.log', level='INFO', encoding="utf-8", rotation="50 MB", retention=3)
异常捕获
使用catch()装饰器或者上下文管理器可以捕获异常,确保任何错误都能够记录到log日志中。
装饰器
from loguru import logger @logger.catch def test(x, y, z): return 1 / (x + y + z) test(0, 1, -1) 1234567
上下文装饰器
from loguru import logger def test(x, y, z): return 1 / (x + y + z) with logger.catch(): test(0, 1, -1) 12345678
输出结果
完全描述性异常
记录代码中发生的异常对于跟踪BUG非常重要,loguru允许显示整个堆栈跟踪(包括变量值)来帮助定位BUG原因。
logger.add("out.log", backtrace=True, diagnose=True) # Caution, may leak sensitive data in prod def func(a, b): return a / b def nested(c): try: func(5, c) except ZeroDivisionError: logger.exception("What?!") nested(0) 123456789101112
输出结果
自定义颜色
logger.add(sys.stdout, colorize=True, format="<red>{time}</red> <level>{message}</level>") logger.debug("debug") logger.info("info") logger.success("success") logger.warning("warning") logger.error("error") logger.critical("critical") 1234567
输出结果
异步/线程安全/多进程安全
默认情况下,添加到log的所有接收器都是线程安全的,但他们不是多进程安全的。如果需要实现多进程安全,异步记录日志,需要添加一个enqueue参数:
logger.add("test.log", enqueue = True) 1
结构化日志记录
将消息转化为json字符串以便于传递或者解析,可以使用serialize来配置:
logger.add("test.log", serialize=True, encoding="utf-8") logger.debug("debug") logger.info("info") logger.success("success") logger.warning("warning") logger.error("error") logger.critical("critical") 1234567
输出结果
{"text": "2022-07-28 11:25:44.434 | DEBUG | __main__:<module>:43 - debug\n", "record": {"elapsed": {"repr": "0:00:00.127658", "seconds": 0.127658}, "exception": null, "extra": {}, "file": {"name": "logutil.py", "path": "e:\\GitPorject\\ZanguS1\\ZanguRecorder\\common\\logutil.py"}, "function": "<module>", "level": {"icon": "🐞", "name": "DEBUG", "no": 10}, "line": 43, "message": "debug", "module": "logutil", "name": "__main__", "process": {"id": 15768, "name": "MainProcess"}, "thread": {"id": 10228, "name": "MainThread"}, "time": {"repr": "2022-07-28 11:25:44.434074+08:00", "timestamp": 1658978744.434074}}} {"text": "2022-07-28 11:25:44.436 | INFO | __main__:<module>:44 - info\n", "record": {"elapsed": {"repr": "0:00:00.129653", "seconds": 0.129653}, "exception": null, "extra": {}, "file": {"name": "logutil.py", "path": "e:\\GitPorject\\ZanguS1\\ZanguRecorder\\common\\logutil.py"}, "function": "<module>", "level": {"icon": "ℹ️", "name": "INFO", "no": 20}, "line": 44, "message": "info", "module": "logutil", "name": "__main__", "process": {"id": 15768, "name": "MainProcess"}, "thread": {"id": 10228, "name": "MainThread"}, "time": {"repr": "2022-07-28 11:25:44.436069+08:00", "timestamp": 1658978744.436069}}} {"text": "2022-07-28 11:25:44.438 | SUCCESS | __main__:<module>:45 - success\n", "record": {"elapsed": {"repr": "0:00:00.131648", "seconds": 0.131648}, "exception": null, "extra": {}, "file": {"name": "logutil.py", "path": "e:\\GitPorject\\ZanguS1\\ZanguRecorder\\common\\logutil.py"}, "function": "<module>", "level": {"icon": "✔️", "name": "SUCCESS", "no": 25}, "line": 45, "message": "success", "module": "logutil", "name": "__main__", "process": {"id": 15768, "name": "MainProcess"}, "thread": {"id": 10228, "name": "MainThread"}, "time": {"repr": "2022-07-28 11:25:44.438064+08:00", "timestamp": 1658978744.438064}}} {"text": "2022-07-28 11:25:44.439 | WARNING | __main__:<module>:46 - warning\n", "record": {"elapsed": {"repr": "0:00:00.132645", "seconds": 0.132645}, "exception": null, "extra": {}, "file": {"name": "logutil.py", "path": "e:\\GitPorject\\ZanguS1\\ZanguRecorder\\common\\logutil.py"}, "function": "<module>", "level": {"icon": "⚠️", "name": "WARNING", "no": 30}, "line": 46, "message": "warning", "module": "logutil", "name": "__main__", "process": {"id": 15768, "name": "MainProcess"}, "thread": {"id": 10228, "name": "MainThread"}, "time": {"repr": "2022-07-28 11:25:44.439061+08:00", "timestamp": 1658978744.439061}}} {"text": "2022-07-28 11:25:44.440 | ERROR | __main__:<module>:47 - error\n", "record": {"elapsed": {"repr": "0:00:00.133642", "seconds": 0.133642}, "exception": null, "extra": {}, "file": {"name": "logutil.py", "path": "e:\\GitPorject\\ZanguS1\\ZanguRecorder\\common\\logutil.py"}, "function": "<module>", "level": {"icon": "❌", "name": "ERROR", "no": 40}, "line": 47, "message": "error", "module": "logutil", "name": "__main__", "process": {"id": 15768, "name": "MainProcess"}, "thread": {"id": 10228, "name": "MainThread"}, "time": {"repr": "2022-07-28 11:25:44.440058+08:00", "timestamp": 1658978744.440058}}} {"text": "2022-07-28 11:25:44.442 | CRITICAL | __main__:<module>:48 - critical\n", "record": {"elapsed": {"repr": "0:00:00.135637", "seconds": 0.135637}, "exception": null, "extra": {}, "file": {"name": "logutil.py", "path": "e:\\GitPorject\\ZanguS1\\ZanguRecorder\\common\\logutil.py"}, "function": "<module>", "level": {"icon": "☠️", "name": "CRITICAL", "no": 50}, "line": 48, "message": "critical", "module": "logutil", "name": "__main__", "process": {"id": 15768, "name": "MainProcess"}, "thread": {"id": 10228, "name": "MainThread"}, "time": {"repr": "2022-07-28 11:25:44.442053+08:00", "timestamp": 1658978744.442053}}} 123456
使用bind()添加额外的属性:
logger.add("test.log", format="{extra[ip]} {extra[user]} {message}") context_logger = logger.bind(ip="192.168.0.1", user="someone") context_logger.info("Contextualize your logger easily") context_logger.bind(user="someone_else").info("Inline binding of extra attribute") context_logger.info("Use kwargs to add context during formatting: {user}", user="anybody") 12345
输出结果
192.168.0.1 someone Contextualize your logger easily 192.168.0.1 someone_else Inline binding of extra attribute 192.168.0.1 anybody Use kwargs to add context during formatting: anybody 123
使用bind()和filter对日志进行过滤:
logger.add("test.log", filter=lambda record: "special" in record["extra"]) logger.debug("This message is not logged to the file") logger.bind(special=True).info("This message, though, is logged to the file!") 123
输出结果
2022-07-28 11:33:58.214 | INFO | __main__:<module>:58 - This message, though, is logged to the file! 1
自定义级别
Loguru 附带了所有标准日志记录级别,额外添加了trace和success。如果需要自定义级别,可以使用level()函数来创建:
new_level = logger.level("test2", no=66, color="<black>", icon="🐍") logger.log("test2", "Here we go!") 123
输出结果:
日期时间处理
logger.add("test.log", format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}") logger.debug("debug") logger.info("info") logger.success("success") logger.warning("warning") logger.error("error") logger.critical("critical") 1234567
输出结果:
2022-07-28 at 11:41:32 | DEBUG | debug 2022-07-28 at 11:41:32 | INFO | info 2022-07-28 at 11:41:32 | SUCCESS | success 2022-07-28 at 11:41:32 | WARNING | warning 2022-07-28 at 11:41:32 | ERROR | error 2022-07-28 at 11:41:32 | CRITICAL | critical 123456
loguru配置
在脚本中使用记录器很容易,您可以在开始时configure()它。要从库中使用 Loguru,请记住永远不要调用 add(),而是使用 disable(),以便日志记录函数变为 no-op。如果开发人员希望查看库的日志,他可以再次enable() 它。
# For scripts config = { "handlers": [ {"sink": sys.stdout, "format": "{time} - {message}"}, {"sink": "test.log", "serialize": True}, ], "extra": {"user": "someone"} } logger.configure(**config) # For libraries logger.disable("my_library") logger.info("No matter added sinks, this message is not displayed") logger.enable("my_library") logger.info("This message however is propagated to the sinks") 123456789101112131415
通知程序
Loguru 可以和强大的邮件通知模块 notifiers
库结合使用,以在程序意外失败时接收电子邮件,或发送许多其他类型的通知。
import notifiers params = { "username": "you@gmail.com", "password": "abc123", "to": "dest@gmail.com" } # Send a single notification notifier = notifiers.get_notifier("gmail") notifier.notify(message="The application is running!", **params) # Be alerted on each error message from notifiers.logging import NotificationHandler handler = NotificationHandler("gmail", defaults=params) logger.add(handler, level="ERROR") 1234567891011121314151617
尾语
希望能帮助到大家,如果又说的不对的地方,欢迎大家指正。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)