Python CSV 导入:处理 BOM、跨行字段与列数校验

举报
yd_237867988 发表于 2026/11/12 10:16:00 2026/11/12
【摘要】 使用 Python 标准库 csv 读取带 BOM、逗号及跨行字段的 CSV,明确校验固定表头和列数,并用本地样例说明逻辑记录编号、物理行数与错误处理边界。

Python CSV 导入:处理 BOM、跨行字段与列数校验

CSV 导入的难点往往藏在很短的样例之外:备注中可以有逗号,字段可以包含换行,从其他工具导出的 UTF-8 文件还可能带 BOM。如果直接逐行 split(‘,’),这些合法内容会被拆成错误的列。本文用 Python 标准库实现一个只接受固定两列表头的读取函数,并用本地样例验证结构边界。

先明确输入约定

示例只接受 UTF-8 编码的文件,可带 BOM;第一条记录必须严格是 name,note,顺序不可交换。每条后续记录必须恰好两列。空字符串是允许的字段值,空白记录会因为列数不足而被拒绝。这里校验的是结构,姓名是否为空、长度是否合法等业务规则需要另外添加。

读取函数

import csv

def load_records(path):
    with open(path, encoding="utf-8-sig", newline="") as stream:
        reader = csv.reader(stream, strict=True)
        if next(reader, None) != ["name", "note"]:
            raise ValueError("表头必须为 name,note")
        records = []
        for record_no, row in enumerate(reader, start=2):
            if len(row) != 2:
                raise ValueError(f"第 {record_no} 条逻辑记录列数错误")
            records.append(dict(zip(["name", "note"], row)))
        return records

utf-8-sig 解码会去掉文件开头的 UTF-8 BOM,也能读取没有 BOM 的 UTF-8 文件。它不是通用编码探测器,不能因此承诺兼容 GBK 或任意电子表格导出格式。

newline=“” 把换行处理留给 csv 模块,避免文本层预先把字段中的 CRLF 统一变为 LF。csv.reader 负责理解引号、分隔符和跨行字段,不需要自己按逗号或物理行切分。strict=True 会在解析器认定输入不合法时抛出 csv.Error,但它不是完整的业务校验器,所以代码仍明确检查表头和列数。

先验证列数再 zip 很有必要。zip 遇到较短一方就结束,如果省略检查,多出的列可能被丢弃,少列的记录也可能被悄悄接受。

构造可复现输入

将下面代码接在函数之后运行,只会在临时目录中创建测试文件:

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "records.csv"
    data = 'name,note\r\nAlice,"hello, world"\r\nBob,"line1\r\nline2"\r\n'
    path.write_bytes(data.encode("utf-8-sig"))
    rows = load_records(path)
    assert rows == [
        {"name": "Alice", "note": "hello, world"},
        {"name": "Bob", "note": "line1\r\nline2"},
    ]
    print("合法样例通过")

本地实际验证中,BOM 没有混入 name 表头,带逗号的备注保持为一列,Bob 的备注保留了内部 CRLF。另测空文件、错误表头、少列和多列四种输入,均被 ValueError 拒绝。这些结果只覆盖所列样例,不代表所有 CSV 方言都能被此函数接受。

记录编号和错误处理的边界

这里的 record_no 是包含表头的逻辑记录编号。跨行字段会占用多条物理行,错误信息不应将该编号称作文件行号。需要排查物理位置时,可以参考 reader.line_num,它表示解析器已经读过的源文件行数,也不等同于逻辑记录起始行。

调用方还应分别处理文件访问错误 OSError、解码错误 UnicodeDecodeError、CSV 解析错误 csv.Error,以及本函数主动抛出的 ValueError。示例返回列表,适合小文件;大文件应设置大小限制或改为分批处理,同时明确中途失败是否允许已有数据落库。把编码、CSV 解析、结构检查和业务规则分开,导入错误才能被准确定位。

参考:Python 标准库 csv 文档、codecs 文档中的 utf-8-sig 编码说明。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。