Python 读取 CSV:避免乱码、列名异常和编号丢失前导零
CSV 看起来只是逗号分隔的文本,实际导入时却常遇到乱码、表头多出奇怪字符,或编号 0012 变成 12。用 Python 标准库 csv 和 pathlib 读取时,先把编码、换行和字段校验处理好,能避免不少意外。
例如,文件可能是这样:
编号,姓名,城市
0012,林晓,杭州
0045,周宁,成都
可以用 DictReader 按列名读取:
import csv
from pathlib import Path
path = Path("data.csv")
required = {"编号", "姓名", "城市"}
with path.open("r", encoding="utf-8-sig", newline="") as file:
reader = csv.DictReader(file)
headers = reader.fieldnames
if not headers:
raise ValueError("CSV 缺少表头")
headers = [name.strip() for name in headers]
if len(headers) != len(set(headers)):
raise ValueError("清理空格后出现重复列名")
reader.fieldnames = headers
missing = required - set(headers)
if missing:
raise ValueError(f"缺少必需列:{', '.join(sorted(missing))}")
for record, row in enumerate(reader, start=1):
for column in required:
if row.get(column) is None or not row[column].strip():
raise ValueError(f"第 {record} 条记录的“{column}”为空")
identifier = row["编号"]
print(identifier) # 输出 0012,而不是 12
encoding="utf-8-sig" 会兼容带 UTF-8 BOM 的文件,并去掉文件开头的 BOM,避免它混进首列表名;它不能把 GBK 文件转换成 UTF-8。若文件实际为 GBK,应确认来源后使用 encoding="gbk",而不是盲目替换编码或忽略解码错误。
newline="" 是 csv 文档建议的打开方式,让模块自行处理 CSV 换行。with 则在代码块结束或发生异常时自动关闭文件。DictReader 默认将字段读作字符串,不会自动把编号转成整数,因此 0012 的前导零可以保留;如果后续主动做整数转换,前导零仍会丢失。
代码还检查了表头是否存在、必需列是否齐全,以及每条记录的必需字段是否为空或只有空格。这里按数据记录计数;字段内包含换行时,记录编号不等于文件的物理行号。不同来源的 CSV 可能有额外列、分隔符或编码差异;遇到异常时,应先核对文件格式和数据源。
若数据包含个人信息或业务机密,不要把整行内容写入日志;报错时只记录必要的记录编号和列名,并按权限保护原始文件。
官方文档:Python 官方文档中的 csv 模块(CSV File Reading and Writing)。
本文由 AI 辅助撰写,示例数据为虚构。
- 点赞
- 收藏
- 关注作者
评论(0)