Python 读写 CSV:逗号、引号和换行为什么不能自己拼

举报
TechCao 发表于 2026/11/02 06:15:06 2026/11/02
【摘要】 手工拼接逗号无法可靠处理带引号和换行的CSV字段。本文用Python标准库csv演示中文数据的往返读写、newline与编码选择、表头及字段数量检查,并说明空字符串、记录号和数据类型的边界。

把几列数据导出成 CSV,最容易想到的是 ",".join(row);读回来时再调用 split(",")。如果字段只包含简单英文,这种方式看起来能够工作。但真实数据中,备注可能包含逗号,用户名称可能包含双引号,一条说明也可能分成两行。此时,一个物理行不一定是一条记录,一个逗号也不一定代表字段边界。

CSV 的引号有明确规则。例如,字段包含逗号时通常需要加双引号,字段自身的双引号又需要按规则转义。与其让业务代码维护这些细节,更合适的做法是交给 Python 标准库 csv。

写文件:让 writer 处理字段边界

下面的数据刻意包含逗号、双引号和字段内部的换行。它们都是字段内容,不应变成多余的列或记录。

import csv
from pathlib import Path

fields = ["name", "note"]
rows = [
    {"name": "小林", "note": "北京,上海"},
    {"name": "小周", "note": '他说 "收到"'},
    {"name": "小陈", "note": "第一行\n第二行"},
]

path = Path("report.csv")
with path.open("w", encoding="utf-8-sig", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=fields)
    writer.writeheader()
    writer.writerows(rows)

newline="" 是一个容易忽略的参数。它让 csv 模块负责换行处理,避免文本层的换行转换与 CSV 自身规则互相干扰,在 Windows 上尤其有用。它并不是要求所有字段都不能换行。

这里选择 utf-8-sig,让文件开头带有 UTF-8 BOM,便于部分表格软件识别中文。若下游明确要求不带 BOM 的 UTF-8,就改成 utf-8。编码应按实际消费方约定选择,不能把一种写法当成所有系统的默认答案。

读文件:先核对表头,再检查记录形状

读取时同样使用 csv。utf-8-sig 能去掉文件开头的 BOM,也能读取普通的无 BOM UTF-8 文件,避免首个列名变成带隐藏字符的字符串。

with path.open("r", encoding="utf-8-sig", newline="") as f:
    reader = csv.DictReader(f)
    if reader.fieldnames != fields:
        raise ValueError("CSV 表头与约定不一致")

    loaded = []
    for record_no, row in enumerate(reader, start=1):
        if None in row or any(value is None for value in row.values()):
            raise ValueError(f"第 {record_no} 条记录的字段数量不正确")
        loaded.append(row)

assert loaded == rows

这个例子要求表头名称和顺序完全一致。若业务允许列顺序不同,可以单独调整检查规则,但仍应验证必需列,不能直接假定输入一定正确。

DictReader 不是业务校验器:默认情况下,多出的字段会归到 None 这个键下,缺失的字段则可能得到 None 值。代码显式检查这两种情况。空字符串则是另一回事:"" 可以表示一个存在但没有填写的单元格,是否允许为空应由业务规则决定。

报错中的序号叫“记录号”,而不是“文件行号”,因为带换行的字段可能跨越多个物理行。若要定位原始文件,还可以结合 reader.line_num 查看解析器已经读取到的物理行位置。

CSV 解析完成后,还有数据类型这一步

CSV 读出的字段通常是字符串。金额、日期、布尔值等仍需要按明确规则转换;不能因为内容看起来像数字,就把所有字段自动转成数字,否则订单号中的前导零可能丢失。外部内容导入表格软件时,公式解释等展示行为也应另行制定策略,CSV 引号本身并不处理这类业务问题。

验证导出逻辑时,可以构造含中文、逗号、引号、内嵌换行和空字符串的数据,执行“写入再读取”,比较还原结果是否一致。这样检查的是字段内容是否保真,比只查看文件里有几个逗号更有意义。

本文由 AI 辅助撰写。示例已在本地验证特殊字符往返、BOM 与无 BOM 读取,以及表头不匹配、缺列和多列的拒绝行为;表格软件的导入表现未在本文中实测。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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