python loguru
# 从实战角度聊聊Python的Loguru:一个让我改变日志习惯的库
过去好几年,我写Python项目时一直用标准库logging。说实话,那个库功能是够用,可每次配置起来都像在写配置文件——格式字符串、Handler、Formatter、Filter层层嵌套,稍微复杂一点的场景就得花上小半天调教。直到有次处理一个生产环境的问题,同事推荐了Loguru,用了之后才发现,原来日志可以这么用。
Loguru到底是什么
简单讲,Loguru是个第三方日志库,它的核心思想是“你不需要在意日志怎么配置,想打印什么直接写就行”。就拿日常工作来说吧,你要记录错误、调试信息、警告,这些在标准库里面得先写好配置,再创建logger对象,再去调用。Loguru呢?从pip安装后,第一行代码就能直接写“from loguru import logger”,然后logger.info(“XXXX”)就开始工作了。它的设计者显然被标准库的配置折磨过,所以做出来的东西,直接让你跳过所有前置工作。
你可能会问,这听起来像是把配置藏起来了?其实不是。它是把百分之九十的日常用法做到了开箱即用,但同时又保留了足够的弹性来覆盖那另外的百分之十——比如写入文件、格式定制、日志轮转这些。就像一个多功能厨房,常用的工具放在触手可及的位置,偶尔需要的专业设备放在柜子里,但拿出来就能用。
它的特殊之处在哪里
传统日志库最大的痛点不是功能不够,而是“太啰嗦”。我见过不少团队花了半天时间配置logging模块,最后实际写日志的代码只有两行。Loguru解决的是这种不对称问题:
第一个是线程安全。你不需要自己封装锁来处理多线程日志,loguru默认就是线程安全的。记得以前有个项目,就因为忘了给logging加锁,日志文件里混杂着半截的条目,排查起来真是折磨。
第二个是色彩输出。这不是花架子,是真正的生产力工具。终端里日志信息的颜色会被自动归类——错误是红色,警告是黄色,信息是灰色。在调试阶段,你不用盯着大段文本找错误,一眼就能扫到红色的行。
第三个是异常的自动捕获。如果你用logger.catch装饰器包装函数,当一个异常发生时,loguru会自动记录完整的回溯信息,而不是像标准库那样只记录一行error日志。这功能在调试Web请求时特别实用,每个请求的失败都会自动带上完整的traceback。
怎样上手用起来
安装这一步实在没什么可说的:
pip install loguru然后,任何一个Python文件的顶部写:
fromloguruimportlogger这就完成了配置。接着你可以像用print一样用它:
logger.debug("链接数据库尝试开始")response=requests.get(url)ifresponse.status_code!=200:logger.warning(f"接口返回异常:{response.status_code}")else:logger.info("数据获取成功,共 {count} 条",count=len(response.json()))注意到最后一行有个特别的格式:花括号里直接传变量。这和字符串的f-string很像,但loguru会延迟格式化,只有当日志级别被允许输出时才会执行,不会白白消耗性能。
当你需要把日志写进文件时,只需要调用一个方法:
logger.add("logs/app_{time}.log",rotation="1 day",retention="7 days")这一行配置就能做到每天切分一个新文件,保留7天的日志,不需要再折腾什么RotatingFileHandler、TimedRotatingFileHandler,也不必担心忘记设置BackupCount。反过来,你还可以做反向操作,比如把错误级别的日志单独送到一个文件:
logger.add("logs/errors_{time}.log",level="ERROR",rotation="1 week")这样调试时只看普通日志,定位问题时就去看errors文件,分工明确。
实际项目中的一些实践心得
用了几年Loguru后,我总结了一些习惯,算是避坑指南吧。
第一个是不要在import时直接配置add。因为当多个模块都import这个logger时,重复add会导致重复记录。我的做法是单独写一个config_logger.py,在里面集中配置所有的add,然后其他模块只import这个文件或者直接from loguru import logger。
第二个是使用bind添加上下文。比如做一个订单的处理程序,可以在每个worker任务里:
logger=logger.bind(order_id=order.id)logger.info("开始处理订单")# 后面的所有日志都会自动带上order_id这样当你有几十个并行任务时,排查日志就能轻易按订单ID过滤,而不是面对一堆无头的信息。
第三个是记录性能敏感代码时别用format。很多人习惯写成logger.info(f"耗时 {t} 秒"),这在频繁进入的循环里会额外计算字符串格式。Loguru推荐的写法是logger.info(“耗时 {} 秒”, t),或者用str.format传参,确实能省点开销。
第四个是关于异常处理。很多人遇到异常时只写logger.error(str(e)),这样等于丢失了堆栈信息。我习惯的做法是:
try:process(data)exceptException:logger.exception("处理数据失败")# 或者直接 logger.error("处理失败", exc_info=True)这样traceback会自动写入日志,下次看到错误时能看到从哪个函数开始炸的。
与同类技术对比:为什么我推荐它
和标准库logging的对比其实不用多说,Loguru几乎就是为替代它而生的。你如果硬要我说出logging还有什么不可替代的优点,我能想到的就是它是内置库,不用额外安装。但除此之外,如果你需要自定义Handler、使用网络日志、集成ELK或者Sentry,Loguru也都有自己的解决方案,而且通常比手动配置logging要简洁很多。
还有一个叫Structlog的库,它和Loguru的目标不同。Structlog的重心是结构化日志,就是每次输出都是JSON或者字典,方便日志收集系统解析。而Loguru更在意开发者的体验——你看它的文档,大部分篇幅是在讲怎么让日志更好读、更易用,而不是怎么让日志变成机器可读的格式。当然,Loguru也支持序列化输出,只是它不会强迫你用。
相比之下,structlog要求你先理解“事件处理器”和“链条”的概念,配置起来也比Loguru复杂。对于大多数中小型项目,Loguru用起来更直接,团队接手时不需要学习新概念。
如果你想找一个和自己习惯配置的工具,还有rich库,它提供了好看的终端格式化输出,但rich不是日志库,它更像一个增强版的print。你可以用它来美化日志输出,但它的重心不在这,时间长了会感觉不够用。
说到底,选择日志库这件事,考虑的应该是“如果明天一个新人接手这个项目,他能不能在第一眼就知道日志在记录什么”。Loguru在这点上做得很成功——它的API直观,输出的日志易读,配置精简,几乎没有学习曲线。可能正是因为这些,这些年越来越多的Python开源项目默认使用Loguru,而不是再去折腾标准库那套API了。
