当前位置: 首页 > news >正文

16:logging 日志模块

在自动化测试项目中,日志是排查问题的 “第一线索”。当你的用例在 CI/CD 环境中失败、GUI 自动化脚本突然崩溃、接口请求返回异常时,没有日志就等于 “两眼一抹黑”。Python 标准库中的 logging 模块,正是为解决这个问题而生的专业日志工具 —— 它支持多级别日志、多输出目标、自定义格式,是自动化测试项目中必不可少的组件。


一、为什么不用 print,而要用 logging?

很多新手在调试时习惯用 print() 打印信息,但在正式的自动化测试项目中,print 存在致命缺陷:

如:

  • 无法区分日志级别,所有信息混在一起,排查问题时难以筛选;
  • 无法同时输出到控制台和文件,CI/CD 环境中运行后无法回溯日志;
  • 无法自定义日志格式,缺少时间戳、模块名、行号等关键信息;
  • 无法控制日志开关,上线后注释 / 删除所有 print 非常麻烦。

logging 完美解决了这些问题,它支持:

✅ 5 种日志级别,精准控制输出范围

✅ 同时输出到控制台、文件、网络等多个目标

✅ 自定义日志格式,包含时间戳、模块名、行号等调试信息

✅ 灵活的配置方式,支持全局配置和模块化配置


二、logging 基础用法:从全局日志开始

logging 提供了开箱即用的全局配置方式,适合快速调试或小型项目。

示例 1:基础全局日志

import logging # 基础配置:设置日志级别为 INFO(INFO 及以上级别才会输出) logging.basicConfig(level=logging.INFO) # 不同级别的日志 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') # 错误信息 logging.critical('This is a critical message') # 严重错误
日志级别金字塔(从低到高)
DEBUG < INFO < WARNING < ERROR < CRITICAL

  • DEBUG :调试信息,用于开发阶段,记录详细的运行细节;
  • INFO :常规运行信息,记录关键流程节点;
  • WARNING :警告信息,不影响程序运行,但需要关注;
  • ERROR :错误信息,程序部分功能失败;
  • CRITICAL :严重错误,程序无法继续运行。

basicConfig 中设置的 level 决定了只有该级别及以上的日志才会被输出。

level设置为debug时,DEBUG以上输出:

import logging logging.basicConfig(level=logging.DEBUG) # 获取 Logger 对象,名称为当前模块名(推荐,便于区分模块日志) logger = logging.getLogger(__name__) if __name__ == "__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') logger.critical('This is a critical message') # DEBUG以上输出: # DEBUG :__main__:This is a debug message # INFO:__main__:This is an info message # WARNING:__main__:This is a warning message # ERROR:__main__:This is an error message # CRITICAL:__main__:This is a critical message

level设置为WARNING时,输出WARNING以上全部内容:

import logging logging.basicConfig(level=logging.WARNING) # 获取 Logger 对象,名称为当前模块名(推荐,便于区分模块日志) logger = logging.getLogger(__name__) if __name__ == "__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') logger.critical('This is a critical message') # 输出WARNING以上全部内容: # WARNING:__main__:This is a warning message # ERROR:__main__:This is an error message # CRITICAL:__main__:This is a critical message

日志配置 与 日志通用配置 区别:优先取日志配置

import logging #通用配置:修改全局日志级别配置为WARNING logging.basicConfig(level=logging.WARNING) #日志配置:对logger对象设置改日志对象的日志级别为DEBUG logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) if __name__ == "__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') logger.critical('This is a critical message') # 输出DEBUG以上全部内容: # DEBUG:__main__:This is a debug message # INFO:__main__:This is an info message # WARNING:__main__:This is a warning message # ERROR:__main__:This is an error message # CRITICAL:__main__:This is a critical message

三、进阶用法:自定义 Logger 对象

在大型项目中,推荐使用自定义 Logger 对象,而不是全局日志。它的优势是:

  • 支持模块化日志,不同模块的日志可以区分;
  • 支持多个处理器(Handler),同时输出到控制台和文件;
  • 支持独立配置日志级别和格式,灵活性更高。

示例 2:自定义 Logger 并输出到控制台

import logging # 获取 Logger 对象,名称为当前模块名(推荐,便于区分模块日志) logger = logging.getLogger(__name__) # 设置日志级别为 DEBUG(DEBUG 及以上都会输出) logger.setLevel(logging.DEBUG) if __name__ == "__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') logger.critical('This is a critical message')

示例 3:输出日志到文件

通过创建文件处理器 FileHandler,可以将日志同时写入文件,便于后续排查问题:

import logging logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # 创建文件处理器,指定日志文件路径 file_handler = logging.FileHandler(filename="log_test.log", encoding="utf-8") # 将处理器添加到 Logger 对象 logger.addHandler(file_handler) if __name__ == "__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') logger.critical('This is a critical message')

运行后,日志会同时输出到目标文件log_test.log中。


四、高级配置:自定义日志格式

默认的日志输出格式只有信息内容,缺少关键的调试信息(如时间、模块名、行号)。

通过 Formatter 可以自定义日志格式,让每一条日志都包含完整的上下文信息。

示例 4:自定义日志格式

import logging logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # 1. 创建文件处理器 file_handler = logging.FileHandler("test.log", encoding="utf-8") # 2. 创建日志格式器 formatter = logging.Formatter( fmt="%(asctime)s | %(levelname)-8s | %(name)s:%(filename)s:%(lineno)d | %(message)s", datefmt="%Y-%m-%d %H:%M:%S" ) # 3. 将格式器设置到处理器 file_handler.setFormatter(formatter) # 4. 添加处理器到 Logger logger.addHandler(file_handler) if __name__ == "__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') logger.critical('This is a critical message')

对应文件test.log中每一条日志都包含完整的上下文信息

2026-05-25 21:23:30 | DEBUG | __main__:my_logging.py:22 | This is a debug message 2026-05-25 21:23:30 | INFO | __main__:my_logging.py:23 | This is an info message 2026-05-25 21:23:30 | WARNING | __main__:my_logging.py:24 | This is a warning message 2026-05-25 21:23:30 | ERROR | __main__:my_logging.py:25 | This is an error message 2026-05-25 21:23:30 | CRITICAL | __main__:my_logging.py:26 | This is a critical message
常用格式占位符说明
占位符说明
%(asctime)s日志记录的时间戳,格式可自定义
%(levelname)s日志级别(DEBUG/INFO/WARNING/ERROR/CRITICAL)
%(name)sLogger 对象的名称,通常为模块名
%(filename)s日志记录发生的文件名
%(lineno)d日志记录发生的行号
%(funcName)s日志记录发生的函数名
%(message)s日志消息本身

五、自动化测试实战:日志最佳实践

在 GUI / 接口自动化测试项目中,logging 有几个固定的使用场景和最佳实践:

1. 项目级日志配置(推荐)

在项目根目录创建 logger_config.py,统一配置日志,所有模块直接导入使用:

# logger_config.py import logging import os from logging.handlers import RotatingFileHandler def setup_logger(name=__name__, log_file="logs/test.log", max_size=10*1024*1024, backup_count=5): """ 项目级日志配置 :param name: Logger 名称,建议用模块名 :param log_file: 日志文件路径 :param max_size: 单个日志文件最大大小(默认10MB) :param backup_count: 日志文件备份数量 """ # 创建日志目录 os.makedirs(os.path.dirname(log_file), exist_ok=True) logger = logging.getLogger(name) logger.setLevel(logging.DEBUG) # 避免重复添加处理器 if logger.handlers: return logger # 1. 控制台处理器 console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) # 2. 文件处理器(按大小切割日志,避免单个文件过大) file_handler = RotatingFileHandler( log_file, maxBytes=max_size, backupCount=backup_count, encoding="utf-8" ) file_handler.setLevel(logging.DEBUG) # 3. 日志格式 formatter = logging.Formatter( "%(asctime)s | %(levelname)-8s | %(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

在测试用例中直接使用:

# test_login.py from logger_config import setup_logger logger = setup_logger(__name__) def test_login(): logger.info("开始执行登录用例") username = "admin" password = "123456" logger.debug(f"使用账号:{username},密码:{password}") # 模拟登录操作 try: # 这里写实际的登录逻辑 logger.info("登录操作执行完成") except Exception as e: logger.error(f"登录失败:{str(e)}", exc_info=True) raise

2. 关键场景日志记录

  • 用例执行前后:记录用例名称、开始 / 结束时间;
  • 关键操作节点:如打开浏览器、输入账号、点击按钮、接口请求 / 响应;
  • 异常信息: 使用 logger.error("消息", exc_info=True) 记录完整的异常栈信息;
  • 环境信息: 记录测试环境(URL、版本号)、测试数据(避免硬编码)。

3. 日志切割:避免单个日志文件过大

使用 RotatingFileHandler(按大小切割)或 TimedRotatingFileHandler(按时间切割)

自动分割日志文件,避免单个日志文件过大,便于后续归档和排查。


六、常见问题与避坑指南

  1. 日志不输出:检查日志级别设置,确保设置的级别不高于日志调用级别
  2. 日志重复输出:是否多次添加 Handler,在 setup_logger 中添加 if logger.handlers: 判断;
  3. 中文乱码:FileHandler 初始化时指定 encoding="utf-8";
  4. 日志文件路径不存在:提前创建日志目录,使用 os.makedirs(os.path.dirname(log_file), exist_ok=True);
  5. 日志级别不生效:basicConfig 只能配置一次,后续修改无效,推荐使用自定义 Logger 对象。

七、总结

logging 模块是 Python 自动化测试项目中不可或缺的组件,它不仅能帮你记录关键信息,更能在问题发生时提供完整的上下文,大幅提升调试效率。

核心知识点回顾:

  1. 日志级别:DEBUG < INFO < WARNING < ERROR < CRITICAL,通过setLevel控制输出范围;
  2. 三大核心组件:Logger(日志记录器)、Handler(输出处理器)、Formatter(日志格式器);
  3. 最佳实践:项目级统一配置、模块化 Logger、日志切割、关键场景记录。

掌握 logging 的使用,你的自动化测试项目将从 “能跑” 升级为 “可维护、可追溯、易排查” 的专业级项目。后续我们可以结合 Allure 报告,将日志嵌入测试报告中,让失败用例的排查更直观。

http://www.jsqmd.com/news/888946/

相关文章:

  • 基于AI代码助手构建轻量级工作流引擎:从自动化到工程化
  • SUMO车流生成避坑指南:randomTrips.py的-p、-e参数怎么设才不堵车?
  • WinForms数独实战:解剖控件生命周期与UI线程约束
  • AI编程助手成本优化:从日志分析到八大浪费模式根治
  • Unity Spine资源动态化:解耦加载与热更实战指南
  • OAuth 2.0授权码code为什么不可跳过?安全设计本质解析
  • AI Agent 技术全景深度解析:从代码搜索到记忆系统,2026年工程实践的核心战场
  • Unity多语言架构设计:XAT运行时资源治理实战
  • 如何彻底解决Windows系统卡顿:开源优化工具的完整技术方案
  • Android逆向实战:dex2jar深度解析与混淆对抗全链路
  • 从CartPole到ChatGPT:手把手教你用PyTorch复现PPO算法(附完整代码)
  • 基于规则与状态追踪的LLM多轮提示词注入防御实践
  • Windows Cleaner核心技术揭秘:5大架构优势解析与实战部署指南
  • 如何免费解锁Wand专业版功能:Wand-Enhancer完整使用教程
  • 机器学习势函数揭秘Cu/TaN界面力学:原子掺杂如何突破性能瓶颈
  • 说说JVM的常见问题
  • 低资源音乐生成中的适配器设计优化与实践
  • CLI与人格化AI结合:打造社交技能训练工具的技术实现
  • XGBoost与PR-AUC:解决天文数据类别不平衡分类的实践指南
  • DeepSeek熔断失效的4种静默故障模式:从指标漂移到上下文泄漏,附自动检测脚本+Grafana看板模板
  • 千川投手最核心的能力不再是建计划,是用AI拆解“跑量素材”的结构特征——爆款复刻Agent帮你做
  • 2026广东靠谱全屋定制品牌评测选购指南 - 服务品牌热点
  • 深度解析Alas自动化框架:从架构设计到实战应用的完整指南
  • 构建团队心理安全感:从核心理念到工程化实践指南
  • iOS自动化真机调试全链路实践:从签名到WDA适配
  • 大模型选型实战:GPT-4、Claude 3、Llama 3成本与性能深度评测
  • 探索Zotero-Style:重新定义文献管理的美学体验
  • Android Frida反检测实战:内存扫描、ptrace绕过与静默注入
  • 从Go转向Rust迁移指南:靠自觉 vs. 靠编译器
  • 从一次失败的Getshell到成功的XSS:我的文件上传漏洞挖掘复盘笔记