Python中loguru日志库如何使用
1.概述
python
中的日志库logging
使用起来有点像log4j
,但配置通常比较复杂,构建日志服务器时也不是方便。标准库logging
的替代品是loguru
,loguru
使用起来就简单的多。
loguru
默认的输出格式是:时间、级别、模块、行号以及日志内容。loguru
不需要手动创建 logger
,开箱即用,比logging
使用方便得多;另外,日志输出内置了彩色功能,颜色和非颜色控制很方便,更加友好。
loguru
是非标准库,需要事先安装,命令是:**pip3 install loguru
****。**安装后,最简单的使用样例如下:
from loguru import logger logger.debug('hello, this debug loguru') logger.info('hello, this is info loguru') logger.warning('hello, this is warning loguru') logger.error('hello, this is error loguru') logger.critical('hello, this is critical loguru')
上述代码输出:
日志打印到文件的用法也很简单,代码如下:
from loguru import logger logger.add('myloguru.log') logger.debug('hello, this debug loguru') logger.info('hello, this is info loguru') logger.warning('hello, this is warning loguru') logger.error('hello, this is error loguru') logger.critical('hello, this is critical loguru')
上述代码运行时,可以打印到console,也可以打印到文件中去。
2.常见用法
2.1.显示格式
loguru
默认格式是时间、级别、名称 模块和日志内容,其中名称 模块是写死的,是当前文件的__name__
变量,此变量最好不要修改。
工程比较复杂的情况下,自定义模块名称,是非常有用的,容易定界定位,避免陷入细节中。我们可以通过logger.configure
手工指定模块名称。如下如下:
import sys from loguru import logger logger.configure(handlers=[ { "sink": sys.stderr, "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<lvl>{level:8}</>| {name} : {module}:{line:4} | <cyan>mymodule</> | - <lvl>{message}</>", "colorize": True }, ]) logger.debug('this is debug') logger.info('this is info') logger.warning('this is warning') logger.error('this is error') logger.critical('this is critical')
handlers
:表示日志输出句柄或者目的地,sys.stderr
表示输出到命令行终端。
"sink": sys.stderr
,表示输出到终端
"format":
表示日志格式化。<lvl>{level:8}</>
表示按照日志级别显示颜色。8表示输出宽度为8个字符。
"colorize":
True
**:表示显示颜色。
上述代码的输出为:
这里写死了模块名称,每个日志都这样设置也是比较繁琐。下面会介绍指定不同模块名称的方法。
2.2.写入文件
日志一般需要持久化,除了输出到命令行终端外,还需要写入文件。标准日志库可以通过配置文件配置logger,在代码中也可以实现,但过程比较繁琐。loguru相对而已就显得稍微简单一些,我们看下在代码中如何实现此功能。日志代码如下:
import sys from loguru import logger logger.configure(handlers=[ { "sink": sys.stderr, "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<lvl>{level:8}</>| {name} : {module}:{line:4} | <cyan>mymodule</> | - <lvl>{message}</>", "colorize": True }, { "sink": 'first.log', "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |{level:8}| {name} : {module}:{line:4} | mymodule | - {message}", "colorize": False }, ]) logger.debug('this is debug') logger.info('this is info') logger.warning('this is warning') logger.error('this is error') logger.critical('this is critical')
与2.1.唯一不同的地方,
logger.configure
新增了一个handler
,写入到日志文件中去。用法很简单。
上述只是通过logger.configure
设置日志格式,但是模块名不是可变的,实际项目开发中,不同模块写日志,需要指定不同的模块名称。因此,模块名称需要参数化,这样实用性更强。样例代码如下:
import sys from loguru import logger logger.configure(handlers=[ { "sink": sys.stderr, "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<lvl>{level:8}</>| {name} : {module}:{line:4} | <cyan>{extra[module_name]}</> | - <lvl>{message}</>", "colorize": True }, { "sink": 'first.log', "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |{level:8}| {name} : {module}:{line:4} | {extra[module_name]} | - {message}", "colorize": False }, ]) log = logger.bind(module_name='my-loguru') log.debug("this is hello, module is my-loguru") log2 = logger.bind(module_name='my-loguru2') log2.info("this is hello, module is my-loguru2")
logger.bind(module_name='my-loguru')
通过bind方法,实现module_name
的参数化。bind返回一个日志对象,可以通过此对象进行日志输出,这样就可以实现不同模块的日志格式。loguru中自定义模块名称的功能比标准日志库有点不同。通过bind方法,可以轻松实现标准日志
logging
的功能。而且,可以通过bind和logger.configure
,轻松实现结构化日志。
上述代码的输出如下:
2.3.json日志
loguru
保存成结构化json格式非常简单,只需要设置serialize=True
参数即可。代码如下:
from loguru import logger logger.add('json.log', serialize=True, encoding='utf-8') logger.debug('this is debug message') logger.info('this is info message') logger.error('this is error message')
输出内容如下:
2.4.日志绕接
loguru
日志文件支持三种设置:循环、保留、压缩。设置也比较简单。尤其是压缩格式,支持非常丰富,常见的压缩格式都支持,比如:"gz"
, "bz2"
, "xz"
, "lzma"
, "tar"
, "tar.gz"
, "tar.bz2"
, "tar.xz"
, "zip"
。样例代码如下:
from loguru import logger logger.add("file_1.log", rotation="500 MB") # 自动循环过大的文件 logger.add("file_2.log", rotation="12:00") # 每天中午创建新文件 logger.add("file_3.log", rotation="1 week") # 一旦文件太旧进行循环 logger.add("file_X.log", retention="10 days") # 定期清理 logger.add("file_Y.log", compression="zip") # 压缩节省空间
2.5.并发安全
loguru
默认是线程安全的,但不是多进程安全的,如果使用了多进程安全,需要添加参数enqueue=True
,样例代码如下:
logger.add("somefile.log", enqueue=True)
loguru
另外还支持协程,有兴趣可以自行研究。
3.高级用法
3.1.接管标准日志logging
更换日志系统或者设计一套日志系统,比较难的是兼容现有的代码,尤其是第三方库,因为不能因为日志系统的切换,而要去修改这些库的代码,也没有必要。好在loguru
可以方便的接管标准的日志系统。
样例代码如下:
import logging import logging.handlers import sys from loguru import logger handler = logging.handlers.SysLogHandler(address=('localhost', 514)) logger.add(handler) class LoguruHandler(logging.Handler): def emit(self, record): try: level = logger.level(record.levelname).name except ValueError: level = record.levelno frame, depth = logging.currentframe(), 2 while frame.f_code.co_filename == logging.__file__: frame = frame.f_back depth += 1 logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage()) logging.basicConfig(handlers=[LoguruHandler()], level=0, format='%(asctime)s %(filename)s %(levelname)s %(message)s', datefmt='%Y-%M-%D %H:%M:%S') logger.configure(handlers=[ { "sink": sys.stderr, "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<lvl>{level:8}</>| {name} : {module}:{line:4} | [ModuleA] | - <lvl>{message}</>", "colorize": True }, ]) log = logging.getLogger('root') # 使用标注日志系统输出 log.info('hello wrold, that is from logging') log.debug('debug hello world, that is from logging') log.error('error hello world, that is from logging') log.warning('warning hello world, that is from logging') # 使用loguru系统输出 logger.info('hello world, that is from loguru')
输出为:
3.2.输出日志到网络服务器
如果有需要,不同进程的日志,可以输出到同一个日志服务器上,便于日志的统一管理。我们可以利用自定义或者第三方库进行日志服务器和客户端的设置。下面介绍两种日志服务器的用法。
3.2.1.自定义日志服务器
日志客户端段代码如下:
# client.py import pickle import socket import struct import time from loguru import logger class SocketHandler: def __init__(self, host, port): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.connect((host, port)) def write(self, message): record = message.record data = pickle.dumps(record) slen = struct.pack(">L", len(data)) self.sock.send(slen + data) logger.configure(handlers=[{"sink": SocketHandler('localhost', 9999)}]) while True: time.sleep(1) logger.info("Sending info message from the client") logger.debug("Sending debug message from the client") logger.error("Sending error message from the client")
日志服务器代码如下:
# server.py import pickle import socketserver import struct from loguru import logger class LoggingStreamHandler(socketserver.StreamRequestHandler): def handle(self): while True: chunk = self.connection.recv(4) if len(chunk) < 4: break slen = struct.unpack('>L', chunk)[0] chunk = self.connection.recv(slen) while len(chunk) < slen: chunk = chunk + self.connection.recv(slen - len(chunk)) record = pickle.loads(chunk) level, message = record["level"].no, record["message"] logger.patch(lambda record: record.update(record)).log(level, message) server = socketserver.TCPServer(('localhost', 9999), LoggingStreamHandler) server.serve_forever()
运行结果如下:
3.2.2.第三方库日志服务器
日志客户端代码如下:
# client.py import zmq from zmq.log.handlers import PUBHandler from loguru import logger socket = zmq.Context().socket(zmq.PUB) socket.connect("tcp://127.0.0.1:12345") handler = PUBHandler(socket)logger.add(handler) logger.info("Logging from client")
日志服务器代码如下:
# server.py import sys import zmq from loguru import logger socket = zmq.Context().socket(zmq.SUB) socket.bind("tcp://127.0.0.1:12345") socket.subscribe("") logger.configure(handlers=[{"sink": sys.stderr, "format": "{message}"}]) while True: _, message = socket.recv_multipart() logger.info(message.decode("utf8").strip())
3.3.与pytest结合
官方帮助中有一个讲解loguru
与pytest
结合的例子,讲得有点含糊不是很清楚。简单的来说,pytest
有个fixture
,可以捕捉被测方法中的logging
日志打印,从而验证打印是否触发。
下面就详细讲述如何使用loguru
与pytest
结合的代码,如下:
import pytest from _pytest.logging import LogCaptureFixture from loguru import logger def some_func(i, j): logger.info('Oh no!') logger.info('haha') return i + j @pytest.fixture def caplog(caplog: LogCaptureFixture): handler_id = logger.add(caplog.handler, format="{message}") yield caplog logger.remove(handler_id) def test_some_func_logs_warning(caplog): assert some_func(-1, 3) == 2 assert "Oh no!" in caplog.text
测试输出如下:
以上是Python中loguru日志库如何使用的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

MySQL 有免费的社区版和收费的企业版。社区版可免费使用和修改,但支持有限,适合稳定性要求不高、技术能力强的应用。企业版提供全面商业支持,适合需要稳定可靠、高性能数据库且愿意为支持买单的应用。选择版本时考虑的因素包括应用关键性、预算和技术技能。没有完美的选项,只有最合适的方案,需根据具体情况谨慎选择。

文章介绍了MySQL数据库的上手操作。首先,需安装MySQL客户端,如MySQLWorkbench或命令行客户端。1.使用mysql-uroot-p命令连接服务器,并使用root账户密码登录;2.使用CREATEDATABASE创建数据库,USE选择数据库;3.使用CREATETABLE创建表,定义字段及数据类型;4.使用INSERTINTO插入数据,SELECT查询数据,UPDATE更新数据,DELETE删除数据。熟练掌握这些步骤,并学习处理常见问题和优化数据库性能,才能高效使用MySQL。

MySQL数据库性能优化指南在资源密集型应用中,MySQL数据库扮演着至关重要的角色,负责管理海量事务。然而,随着应用规模的扩大,数据库性能瓶颈往往成为制约因素。本文将探讨一系列行之有效的MySQL性能优化策略,确保您的应用在高负载下依然保持高效响应。我们将结合实际案例,深入讲解索引、查询优化、数据库设计以及缓存等关键技术。1.数据库架构设计优化合理的数据库架构是MySQL性能优化的基石。以下是一些核心原则:选择合适的数据类型选择最小的、符合需求的数据类型,既能节省存储空间,又能提升数据处理速度

HadiDB:轻量级、高水平可扩展的Python数据库HadiDB(hadidb)是一个用Python编写的轻量级数据库,具备高度水平的可扩展性。安装HadiDB使用pip安装:pipinstallhadidb用户管理创建用户:createuser()方法创建一个新用户。authentication()方法验证用户身份。fromhadidb.operationimportuseruser_obj=user("admin","admin")user_obj.

直接通过 Navicat 查看 MongoDB 密码是不可能的,因为它以哈希值形式存储。取回丢失密码的方法:1. 重置密码;2. 检查配置文件(可能包含哈希值);3. 检查代码(可能硬编码密码)。

MySQL 可在无需网络连接的情况下运行,进行基本的数据存储和管理。但是,对于与其他系统交互、远程访问或使用高级功能(如复制和集群)的情况,则需要网络连接。此外,安全措施(如防火墙)、性能优化(选择合适的网络连接)和数据备份对于连接到互联网的 MySQL 数据库至关重要。

MySQL Workbench 可以连接 MariaDB,前提是配置正确。首先选择 "MariaDB" 作为连接器类型。在连接配置中,正确设置 HOST、PORT、USER、PASSWORD 和 DATABASE。测试连接时,检查 MariaDB 服务是否启动,用户名和密码是否正确,端口号是否正确,防火墙是否允许连接,以及数据库是否存在。高级用法中,使用连接池技术优化性能。常见错误包括权限不足、网络连接问题等,调试错误时仔细分析错误信息和使用调试工具。优化网络配置可以提升性能

对于生产环境,通常需要一台服务器来运行 MySQL,原因包括性能、可靠性、安全性和可扩展性。服务器通常拥有更强大的硬件、冗余配置和更严格的安全措施。对于小型、低负载应用,可在本地机器运行 MySQL,但需谨慎考虑资源消耗、安全风险和维护成本。如需更高的可靠性和安全性,应将 MySQL 部署到云服务器或其他服务器上。选择合适的服务器配置需要根据应用负载和数据量进行评估。
