Python 读写 CSV 文件实战

Python 读写 CSV 文件实战:纯文本时代的「通用表格协议」

1. CSV 文件:轻量级跨平台数据中转站

CSV (Comma Separated Values) 全称「逗号分隔值」,是一个没有统一官方标准(但有广泛共识)的纯文本格式。在 Daoman Python AI 的实际工程落地中,它的身影几乎无处不在:

  • 数据库的临时导入导出
  • 前后端/不同编程语言系统的「跨语言快递」
  • 中小规模机器学习数据集的快速存储

纯文本是它的最大优势:不管是在 Windows 记事本、Mac Numbers、Linux Vim 还是 Excel 里,都能直接读直接写,完全不需要安装特殊解析软件。

大家默认的 CSV 结构约定:

  1. 纯文本编码友好:常用 UTF-8(跨平台首选)或 GBK(国内 Excel 默认)
  2. 行 = 一条完整记录:比如一行是「关羽的三门课成绩」
  3. 字段分隔清晰:通常用英文逗号 ,,也支持制表符 \t、竖线 | 等(特殊场景用特殊符号)
  4. 表头可选但推荐加:第一行写清楚每一列的含义,方便机器和人理解
  5. 特殊内容用包围符:如果字段里本身有分隔符、换行符、引号,就用双引号 " 把整个字段包起来

2. 用原生 csv 模块写入文件:从简单数据到自定义格式

Python 自带了强大的 csv 标准库,不需要 pip 安装任何第三方包就能覆盖日常 80% 的读写需求。我们先从最基础的场景开始:把关羽张飞等五虎上将的随机成绩存成 scores.csv

基础场景:普通数据 + UTF-8 编码

import csv
import random

# ✅ 必须养成的习惯:
# 1. open 函数用 newline='' 避免 Windows 平台产生多余空行
# 2. 明确指定 encoding='utf-8',防止中文乱码
with open('scores.csv', 'w', encoding='utf-8', newline='') as f:
    # 1. 创建 writer 写入器
    writer = csv.writer(f)
    
    # 2. 先写表头(更清晰)
    writer.writerow(['姓名', '语文', '数学', '英语'])
    
    # 3. 生成模拟数据并逐行写入
    five_tigers = ['关羽', '张飞', '赵云', '马超', '黄忠']
    for name in five_tigers:
        # 列表推导式快速生成 3 门 50-100 的随机成绩
        scores = [random.randint(50, 101) for _ in range(3)]
        # 把姓名插到成绩列表最前面
        scores.insert(0, name)
        writer.writerow(scores)

✨ 运行后用 Excel 打开试试?记得选「UTF-8 逗号分隔」格式,中文就能正常显示啦!

进阶场景:自定义分隔符 + 包围符

有时候你会遇到一些「奇怪的 CSV」:

  • 比如用竖线 | 分隔(因为数据里本身有很多逗号)
  • 或者所有字段都加双引号(避免歧义的通用做法)

这时候就需要给 csv.writer 传参数了:

import csv
import random

with open('custom_scores.csv', 'w', encoding='utf-8', newline='') as f:
    # 🎯 自定义参数:
    # delimiter='|' → 用竖线而不是逗号
    # quoting=csv.QUOTE_ALL → 给所有字段加双引号
    writer = csv.writer(
        f,
        delimiter='|',
        quoting=csv.QUOTE_ALL
    )
    
    writer.writerow(['姓名', '备注', '语文', '数学', '英语'])
    five_tigers = ['关羽', '张飞', '赵云', '马超', '黄忠']
    notes = ['桃园结义二弟', '桃园结义三弟', '长坂坡英雄', '锦马超', '百步穿杨']
    for name, note in zip(five_tigers, notes):
        scores = [random.randint(50, 101) for _ in range(3)]
        # 把姓名和备注插进去
        row = [name, note] + scores
        writer.writerow(row)

3. 用原生 csv 模块读取文件:逐行迭代到字典式读取

读取数据有两种最常用的方式:列表式读取(适合简单场景)字典式读取(推荐,直接关联表头和值)

方式一:列表式读取(csv.reader

import csv

with open('scores.csv', 'r', encoding='utf-8') as f:
    # 创建 reader 迭代器(注意迭代器只能遍历一次!)
    reader = csv.reader(f)
    for row in reader:
        # row 是一个字符串列表(不管原来存的是数字还是中文)
        print(f"第 {reader.line_num} 行数据:", row)

方式二:字典式读取(csv.DictReader,强烈推荐!)

如果你不想每次都靠索引 row[0] 来取「姓名」,靠 row[1] 来取「语文」,就用 DictReader 吧——它会自动把表头作为字典的键,值作为字典的值:

import csv

with open('scores.csv', 'r', encoding='utf-8') as f:
    # 创建 DictReader 迭代器
    reader = csv.DictReader(f)
    # 可以先打印看看表头
    print("表头:", reader.fieldnames)
    print("-" * 40)
    for row in reader:
        # 直接通过键名取数据,语义清晰多了!
        print(f"{row['姓名']}的成绩:语文{row['语文']},数学{row['数学']},英语{row['英语']}")

📌 小提示:如果是读取刚才自定义的竖线分隔文件,记得在创建 reader/DictReader 的时候也加 delimiter='|' 哦!


4. 实战避坑指南(新手必看!)

虽然 csv 模块看起来简单,但踩坑的人可不少:

坑1:中文乱码

  • 原因:编码不匹配(比如用 GBK 写入,用 UTF-8 读取,或者反过来)
  • 解决:写入和读取都明确指定同一个 encoding,国内 Excel 默认是 GBK,其他场景优先用 UTF-8。

坑2:Windows 平台出现多余空行

  • 原因:Windows 系统默认的换行符是 \r\n,而 csv 模块会自动处理换行,不需要 open 函数的默认换行功能
  • 解决:写入时 open 函数必须加 newline=''

坑3:把 reader 迭代器转成列表后再遍历多次没问题,但要注意内存占用

  • 如果是几万行以内的小文件,直接转成列表 data = list(reader) 没问题;
  • 如果是几十万行的大文件,最好逐行处理,避免一次性把整个文件加载到内存里。

5. 总结与前瞻:原生 csv 是基础,Pandas 是核武器

原生 csv 模块的适用场景

  • 中小规模 CSV 文件(几万行以内)的快速读写
  • 需要高度自定义格式的场景
  • 不想安装第三方包的轻量级项目

进阶神器 Pandas 的威力

Daoman Python AI 涉及的大规模数据分析、机器学习场景中,我们几乎不用原生 csv,而是直接用 Pandas

  1. 一行代码读取/写入pd.read_csv()df.to_csv()
  2. 直接转成 DataFrame:这是一种类似 Excel 的二维表结构,支持筛选、排序、聚合、缺失值处理等操作,一行代码顶原生几十行
  3. 性能优势明显:对于几十万甚至百万行的文件,Pandas 处理速度更快,代码更简洁

下一篇文章,我们就会介绍 Pandas 读写 CSV 的用法,敬请期待!