Py学习  »  Python

Python 日志抓狂?Loguru + 实战技巧让你告别 "黑盒" 调试

数据派THU • 1 月前 • 282 次点击  
图片
本文约1800字,建议阅读5分钟

Python 日志配置不再难,Loguru 极简用法 + 标准库封装,高效定位问题。


你是否曾为Python日志配置抓狂?那么多部件:处理器、格式器、级别、配置……感觉就像在组装一件缺少说明书的IKEA家具,最后还装反了!


别担心,今天我要分享的这个简单技巧,将彻底改变你对Python日志记录的印象。


为什么Python日志记录让人如此头疼?


1. 样板代码太多


每个教程开头都是这样一大段:


import loggingfrom logging.handlers import RotatingFileHandlerlogger = logging.getLogger('MyApp')handler = logging.StreamHandler()file_handler = RotatingFileHandler('app.log', maxBytes=5*1024*1024, backupCount=10)formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')handler.setFormatter(formatter)file_handler.setFormatter(formatter)logger.addHandler(handler)logger.addHandler(file_handler)logger.setLevel(logging.DEBUG)


等打完这些,咖啡早就凉了!


2. 错误信息像天书


"日志怎么没显示?哦,是因为忘了设置处理器,处理器又忘了设置格式器,格式器又忘了设置级别……" 日志像前任一样已读不回!


3. 日志级别让人困惑


DEBUG、INFO、WARNING、ERROR、CRITICAL——听起来简单,但问5个开发者什么是INFO、什么是DEBUG,你会得到10个答案!


拯救你的神器:Loguru


认识一下Loguru,这个库会让你的日志记录变得异常简单。


极简配置


from loguru import loggerlogger.add(    "logs/app.log"    level="DEBUG"    format="{time:YYYY-MM-DD HH:mm:ss} - {level} - {file} - {line} - {message}",    rotation="10 MB")logger.info('可以写日志了')


不需要创建文件夹,不需要设置复杂的处理器,一行配置就搞定一切!


错误追踪变得简单


Loguru能精准定位问题,每个变量的值都会给你标出来:


from loguru import logger@logger.catchdef test():    'a' + 1test()


运行后会显示详细的错误信息,包括每个变量的值,调试效率大大提升!


为什么Loguru是救星?


1. 开箱即用


无需复杂配置,导入即可开始记录日志。同一个项目中其他文件直接使用相同的logger:


from loguru import loggerlogger.info('直接使用,无需额外配置')


2. 强大的功能


Loguru内置了许多实用功能:


  • 自动日志轮转:防止日志文件过大

  • 异常捕获:使用装饰器自动记录异常

  • 色彩支持:控制台输出自带色彩,更容易阅读

  • 异步记录:不影响主程序性能


3. 结构化日志


# 记录结构化数据logger.info("用户操作", user_id=123, action="login", success=True)


这样的日志更容易被日志系统分析和查询。


传统logging还能抢救一下吗?


当然!如果你因项目限制必须使用标准logging库,这里有个简化方案:


创建可重用的日志工具函数


import loggingimport osdef setup_logger(name=None, level=logging.INFO):    """设置并返回一个配置好的logger实例"""        # 创建logger    logger = logging.getLogger(name or __name__)    logger.setLevel(level)        # 如果已经有处理器,避免重复添加    ifnot logger.handlers:        # 创建控制台处理器        console_handler = logging.StreamHandler()        console_handler.setLevel(level)                # 创建文件处理器(可选)        os.makedirs('logs', exist_ok=True)        file_handler = logging.handlers.RotatingFileHandler(            'logs/app.log', maxBytes=5*1024*1024, backupCount=3, encoding='utf-8'        )        file_handler.setLevel(level)                # 设置格式        formatter = logging.Formatter(            '%(asctime)s - [%(levelname)s] - %(name)s - %(filename)s:%(lineno)d - %(message)s',            datefmt='%Y-%m-%d %H:%M:%S'        )                console_handler.setFormatter(formatter)        file_handler.setFormatter(formatter)                # 添加处理器        logger.addHandler(console_handler)        logger.addHandler(file_handler)        return logger# 使用示例logger = setup_logger("my_app")logger.info("日志变得简单了!")


这个函数可以在项目的任何模块中重用,确保一致的日志配置。


实用场景示例


Web开发中的日志记录


from fastapi import FastAPIfrom loguru import loggerapp = FastAPI()@app.middleware("http")asyncdef log_requests(request, call_next):    logger.info(f"请求: {request.method} {request.url}")    response = await call_next(request)    logger.info(f"响应: {response.status_code}")    return response@app.get("/")asyncdef read_root():    logger.info("访问根路径")    return {"Hello""World"}


数据处理中的进度跟踪


from loguru import loggerdef process_data(data):    total = len(data)    for i, item in enumerate(data):        # 处理数据...        if i % 100 == 0:            logger.info(f"进度: {i}/{total} ({i/total*100:.1f}%)")        logger.debug(f"处理项目: {item}")        logger.success(f"数据处理完成,共处理 {total} 条记录")


脚本调试


from loguru import logger@logger.catchdef main():    logger.info("脚本开始执行")        # 你的代码在这里    # 任何异常都会被自动记录        logger.info("脚本执行完成")if __name__ == "__main__":    main()


日志最佳实践


1. 选择合适的日志级别

  • DEBUG:详细的调试信息,适用于开发环境

  • INFO:确认程序按预期运行

  • WARNING:表明已发生或即将发生意外(如磁盘空间不足)

  • ERROR:由于严重问题,程序的某些功能已经不能正常执行

  • CRITICAL:重错误,表明程序已不能继续执行


2. 日志中包含上下文信息


# 不好的做法logger.error("操作失败")# 好的做法logger.error("用户操作失败", user_id=user_id, action=action, reason=error_msg)


3. 生产环境考虑性能


# 避免在循环中使用字符串格式化if logger.isEnabledFor(logging.DEBUG):    expensive_data = generate_expensive_debug_data()    logger.debug("数据: %s", expensive_data)


写在最后


Python日志记录从让人头疼到得心应手,只需要一个正确的工具和方法。Loguru让日志记录变得简单直观,而合理的封装也能让标准logging库变得易用。


记住,良好的日志记录就像飞机的黑匣子,当程序出现问题时,它能帮你快速定位原因,节省大量调试时间。


现在,是时候告别杂乱的print语句,拥抱高效的日志记录了!


编辑:于腾凯




关于我们

数据派THU作为数据科学类公众号,背靠清华大学大数据研究中心,分享前沿数据科学与大数据技术创新研究动态、持续传播数据科学知识,努力建设数据人才聚集平台、打造中国大数据最强集团军。



图片


新浪微博:@数据派THU

微信视频号:数据派THU

今日头条:数据派THU

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/189907