3. 文件与数据操作:读写文本、CSV、JSON、Excel文件

在自动化测试与仪器控制场景中,数据是测试结果的载体,也是后续分析与决策的基础。无论是记录电压采样序列、保存仪器配置参数,还是导出测试报告,都离不开对文件系统的读写操作。Python 标准库与第三方库提供了从简单文本到结构化二进制格式的完整解决方案。本章将系统讲解文本文件、CSV、JSON 与 Excel 四种主流格式的读写方法,并结合仪器控制场景给出数据记录与结果导出的最佳实践。

Python 文件与数据操作全景图 数据源 仪器采样 / 测试结果 配置参数 / 日志记录 Python 数据处理核心 文本 CSV JSON Excel 输出目标 测试报告 / 数据文件 数据库 / 可视化 操作流程:打开 → 读取/写入 → 处理 → 关闭/保存 → 异常处理 关键要点 • 编码统一(UTF-8) • 上下文管理器(with) • 大文件分块处理 • 路径处理(pathlib) • 异常捕获与重试 格式对比 文本:简单,无结构 CSV:表格,轻量 JSON:嵌套,可读 Excel:格式化,多表 选择依据:数据复杂度 最佳实践 • 数据校验与清洗 • 原子写入(临时文件) • 日志记录操作过程 • 定期归档与备份 • 性能监控与优化

3.1 文本文件读写:基础与编码管理

核心原理

文本文件是最基础的数据存储形式,Python 通过内置的 open() 函数实现读写操作。其核心机制是文件对象(file object)与操作系统文件描述符之间的映射。在自动化测试中,文本文件常用于保存仪器日志、配置参数或简单的测量结果。关键参数包括:文件路径、打开模式(r 读、w 写、a 追加)、编码方式(默认 UTF-8)。

操作流程

  1. 路径解析:使用 pathlib.Path 处理跨平台路径,避免硬编码字符串拼接。
  2. 打开文件:推荐使用 with 上下文管理器,自动处理资源释放。
  3. 读写操作:按行读取(readline())或整体读取(read()),写入时注意换行符。
  4. 异常处理:捕获 FileNotFoundError、PermissionError 等。
from pathlib import Path
import logging

def write_log(file_path: Path, content: str):
    """安全写入日志文件"""
    try:
        with file_path.open('a', encoding='utf-8') as f:
            f.write(f"{content}\n")
    except PermissionError:
        logging.error(f"无权限写入: {file_path}")
    except Exception as e:
        logging.error(f"写入失败: {e}")

# 使用示例
log_path = Path("test_results") / "session.log"
write_log(log_path, "2025-01-15 10:30:00 - 测试开始")
编码陷阱:Windows 系统默认使用 GBK 编码,若读取 UTF-8 文件未指定编码,会出现 UnicodeDecodeError。建议所有文件操作显式指定 encoding='utf-8'。

3.2 CSV 文件:结构化数据存储

核心原理

CSV(Comma-Separated Values)是测试数据交换的标准格式。Python 的 csv 模块提供读写器(reader/writer)和字典读写器(DictReader/DictWriter)。在仪器控制中,CSV 常用于保存多通道采样数据、测试用例参数表等。其优势在于轻量、通用、可直接用 Excel 打开。

操作流程与案例

场景推荐方式关键参数
简单列表数据csv.writerdelimiter=',', lineterminator='\n'
带表头数据csv.DictWriterfieldnames 定义列名
大文件读取迭代器逐行处理避免一次性加载内存
import csv
from pathlib import Path

def save_measurements(file_path: Path, data: list[dict]):
    """保存仪器测量数据到 CSV"""
    fieldnames = ['timestamp', 'channel', 'voltage', 'current']
    with file_path.open('w', newline='', encoding='utf-8') as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(data)

# 模拟数据
measurements = [
    {'timestamp': '10:00:01', 'channel': 'CH1', 'voltage': 3.3, 'current': 0.12},
    {'timestamp': '10:00:02', 'channel': 'CH2', 'voltage': 5.0, 'current': 0.08},
]
save_measurements(Path("data") / "measurements.csv", measurements)
经验提醒:写入 CSV 时务必使用 newline='' 参数,否则在 Windows 上会出现空行。读取时若数据包含中文,需指定 encoding='utf-8-sig' 以兼容 Excel 打开。

3.3 JSON 文件:配置与复杂数据交换

核心原理

JSON(JavaScript Object Notation)是层级化数据交换的标准格式。Python 的 json 模块提供 dump/dload 和 dumps/loads 两组接口。在自动化测试中,JSON 常用于保存仪器配置参数、测试环境定义、多级嵌套的测试结果。其核心优势是结构清晰、支持嵌套、跨语言兼容。

实战场景:仪器配置管理

假设我们需要管理多台仪器的配置参数,包括设备地址、采样率、量程等。JSON 的嵌套结构可以完美表达这种层级关系。

import json
from pathlib import Path

def load_config(config_path: Path) -> dict:
    """加载仪器配置"""
    try:
        with config_path.open('r', encoding='utf-8') as f:
            return json.load(f)
    except json.JSONDecodeError as e:
        raise ValueError(f"配置文件格式错误: {e}")

def save_config(config: dict, config_path: Path):
    """保存配置,保持可读性"""
    with config_path.open('w', encoding='utf-8') as f:
        json.dump(config, f, indent=2, ensure_ascii=False)

# 配置示例
config = {
    "instruments": {
        "scope": {"model": "DS1054Z", "address": "USB0::0x1AB1::0x04CE::DS1ZA12345::INSTR"},
        "dmm": {"model": "34461A", "address": "TCPIP0::192.168.1.100::inst0::INSTR"}
    },
    "sampling": {"rate": 1000, "points": 10000}
}
save_config(config, Path("config") / "instruments.json")
性能优化:对于大型 JSON 文件(>10MB),建议使用 ijson 库进行流式解析,避免内存溢出。在仪器控制中,若需频繁读写配置,可考虑使用 json.dump 的 sort_keys=True 参数保持键顺序稳定。

3.4 Excel 文件:报告生成与数据分析

核心原理

Excel 是测试报告的标准格式。Python 中主流的库是 openpyxl(处理 .xlsx)和 xlrd/xlwt(处理 .xls)。openpyxl 支持样式、公式、图表等高级功能,适合生成专业测试报告。在仪器控制中,Excel 常用于保存最终测试结果、生成批量测试报告。

操作流程

  1. 创建工作簿:Workbook() 创建新文件,或 load_workbook() 加载现有文件。
  2. 选择工作表:active 获取默认表,create_sheet() 新建表。
  3. 写入数据:按单元格(cell(row, col))或按行追加(append())。
  4. 样式设置:字体、边框、对齐、列宽等。
  5. 保存文件:save() 方法。
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment
from pathlib import Path

def generate_report(file_path: Path, results: list[dict]):
    """生成测试报告 Excel"""
    wb = Workbook()
    ws = wb.active
    ws.title = "测试结果"
    
    # 设置表头
    headers = ["测试项", "通道", "测量值", "单位", "状态"]
    ws.append(headers)
    for cell in ws[1]:
        cell.font = Font(bold=True, color="FFFFFF")
        cell.fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid")
        cell.alignment = Alignment(horizontal="center")
    
    # 写入数据
    for result in results:
        ws.append([result["item"], result["channel"], result["value"], result["unit"], result["status"]])
    
    # 调整列宽
    for col in ws.columns:
        max_length = max(len(str(cell.value)) for cell in col)
        ws.column_dimensions[col[0].column_letter].width = max_length + 2
    
    wb.save(file_path)

# 使用示例
test_results = [
    {"item": "电压校准", "channel": "CH1", "value": 3.3001, "unit": "V", "status": "PASS"},
    {"item": "电流测量", "channel": "CH2", "value": 0.1205, "unit": "A", "status": "PASS"},
]
generate_report(Path("reports") / "test_report.xlsx", test_results)
兼容性注意:openpyxl 不支持 .xls 旧格式,若需处理旧文件请使用 xlrd。另外,Excel 单表最大行数为 1,048,576,超过需分表存储。

3.5 数据记录与导出的综合策略

格式选择决策表

数据特征推荐格式理由
简单日志、单值记录文本轻量、易读、追加方便
表格化采样数据CSV通用、可直接导入分析工具
配置参数、嵌套结构JSON层级清晰、跨语言兼容
正式测试报告Excel格式化、图表、多工作表

案例拆解:多格式数据记录系统

背景:某电源测试系统需要记录 24 小时连续监测数据,包括电压、电流、温度三个通道,每 10 秒采样一次,同时需要生成日报表。

约束:数据量约 8,640 条/天;需要实时追加;日报表需包含统计信息(平均值、最大值、最小值)。

方案:

  1. 实时数据写入 CSV(追加模式),每条记录包含时间戳和三个通道值。
  2. 每小时生成 JSON 摘要文件,包含该小时的统计信息。
  3. 每日结束后,读取 CSV 生成 Excel 日报表,包含原始数据、统计图表。

实施步骤:

import csv, json
from pathlib import Path
from datetime import datetime

class DataRecorder:
    def __init__(self, base_dir: Path):
        self.base_dir = base_dir
        self.csv_path = base_dir / "raw_data.csv"
        self._init_csv()
    
    def _init_csv(self):
        if not self.csv_path.exists():
            with self.csv_path.open('w', newline='') as f:
                writer = csv.writer(f)
                writer.writerow(["timestamp", "voltage", "current", "temperature"])
    
    def record(self, voltage: float, current: float, temp: float):
        with self.csv_path.open('a', newline='') as f:
            writer = csv.writer(f)
            writer.writerow([datetime.now().isoformat(), voltage, current, temp])
    
    def generate_hourly_summary(self):
        # 读取最近一小时数据,计算统计值,写入 JSON
        pass
    
    def generate_daily_report(self):
        # 读取全天数据,生成 Excel 报告
        pass

结果与复盘:该系统运行稳定,CSV 文件大小约 2MB/天,Excel 报告生成时间小于 5 秒。关键经验:CSV 追加写入性能优异,适合高频数据;JSON 摘要便于快速查看;Excel 报告满足管理层需求。

3.6 常见误区与最佳实践

常见误区

  • 忽略编码:不指定编码导致跨平台乱码。
  • 资源泄漏:忘记关闭文件句柄,尤其在异常情况下。
  • 一次性加载大文件:导致内存溢出。
  • 路径硬编码:使用字符串拼接,跨平台失败。
  • 忽略异常:文件操作失败未处理,程序崩溃。

最佳实践清单

  1. 始终使用 with 语句管理文件资源。
  2. 统一使用 pathlib.Path 处理路径。
  3. 显式指定编码为 utf-8。
  4. 大文件使用迭代器或分块读取。
  5. 写入操作考虑原子性(先写临时文件再重命名)。
  6. 记录文件操作日志,便于排障。
  7. 定期备份重要数据文件。
性能调优:当需要频繁写入大量数据时,可考虑使用 pandas 库的 to_csv() 和 to_excel() 方法,其底层采用 C 语言优化,性能比纯 Python 实现提升 5-10 倍。但需注意 pandas 的内存占用,对于超大文件仍需分块处理。

掌握文件与数据操作是自动化测试系统的基础能力。通过合理选择格式、规范操作流程、注意异常处理,可以构建稳定高效的数据记录与导出模块。在实际项目中,建议根据数据特征、使用场景和下游工具兼容性综合选择格式,并建立统一的数据管理规范。