首页/数据/数据工程与 ETL 速查/CSV 处理的常见陷阱
管道基础52 条

CSV 处理的常见陷阱

CSV 看起来简单,实际布满陷阱:分隔符与引号转义、编码与 BOM、换行符、空值与 NULL 的表示、超大数字精度。入库前统一规范比事后清洗省力。

为什么 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),可以把编码与类型问题一次性消除。

易错点

  • 默认方言(分隔符/引号)不同会导致解析偏差,读入时显式声明 dialect
  • 用逐行 split(',') 解析 CSV 在含引号字段时必然出错,直接用 csv 库
  • 带 BOM 的 UTF-8 文件按普通 UTF-8 解析,第一列列名会带不可见字符
  • 把含前导零的编号当数字读入,0 前缀被吃掉后无法还原
  • 字段内换行未启用引号支持,一条记录被拆成多条造成行数翻倍

数据来源与参考

  • RFC 4180 Common Format and MIME Type for CSV Files
  • Python 官方文档 csv 模块
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌