为什么 CSV 容易出错
CSV 看起来只是逗号加换行,实际上没有统一的元信息:分隔符、引号规则、编码、换行符、空值与 NULL 的表达全都靠双方约定。一旦约定不一致,解析出来的列就会整体错位或数据被静默截断,而且往往在入库很久之后才被发现。理解 RFC 4180 的转义规则,并且在读入时显式声明方言,是避免这类问题最省事的做法。
陷阱
| 问题 | 表现 | 处理 |
|---|---|---|
| 引号转义 | 字段内含逗号/引号被切错列 | 按 RFC 4180 规则处理,使用成熟库 |
| 编码 | 中文乱码或出现 BOM 前缀 | 统一 UTF-8,明确是否带 BOM |
| 空值语义 | 空字符串与 NULL 混淆 | 入库前定义缺失值表示法 |
| 大数字 | Excel 打开身份证/订单号变科学计数 | 以文本读取,不要用表格软件直开 |
| 换行符 | 字段内换行把一行拆成两行 | 启用支持引号内换行的解析器 |
| 列顺序 | 增删列后按位置映射全部错位 | 带表头并按列名映射 |
Python 写出规范 CSV
Python 写出规范 CSV
import csv
with open('out.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f, quoting=csv.QUOTE_MINIMAL)
writer.writerow(['id', 'name', 'note'])
writer.writerow(['1001', '其其', '含,逗号 与 "引号"']) # 自动加引号转义
# 读入时显式声明方言,避免默认值不符预期
with open('out.csv', newline='', encoding='utf-8-sig') as f:
for row in csv.DictReader(f):
print(row['id'], row['name'])典型使用场景
- 业务人员提供的数据文件:先抽查编码与前几行,再确定解析参数
- 系统间导出导入:固定列顺序与缺失值表示,并写进接口文档
- 大数据导入前的预检:统计列数与字段类型,提前发现错列
- 中文内容导出:用带 BOM 或不带 BOM 的 UTF-8 要与消费方约定一致
- 日期与金额字段:明确格式与小数位,避免解析成不同时区或精度丢失
多个系统约定不同(有的 NULL 写空、有的写 \N),链路两端必须对齐缺失值表示。
CSV 适合人工查看与低频交换;管道内部传输优先用带类型的格式(Parquet、Avro),可以把编码与类型问题一次性消除。