← 返回题目列表

Python 如何正确读写 CSV 文件?csv.reader、DictReader 和 newline 参数要注意什么?

高频 中等 第 7 / 27 题 更新于 2026/07/27
CSVcsv模块文件读写

简化版

Python 读写 CSV 推荐使用标准库 csv,不要自己用 split(",") 解析。普通行用 csv.reader / csv.writer,按列名处理用 DictReader / DictWriter;打开文件时通常要指定 encoding,并在写入或读取 CSV 时使用 newline=""csv 模块正确处理换行。

详细版

基础读取:

import csv

with open("users.csv", "r", encoding="utf-8", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

按字典读取:

with open("users.csv", "r", encoding="utf-8", newline="") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row["name"])

写入 CSV:

with open("users.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["id", "name"])
    writer.writerow([1, "Alice"])

常见注意点:

  • 不要用字符串 split(",") 解析 CSV,因为字段里可能包含逗号、引号和换行;
  • newline="" 很重要,尤其在 Windows 上可以避免多余空行等问题;
  • 中文 CSV 建议显式指定 encoding,和数据来源保持一致;
  • Excel 场景有时需要 utf-8-sig 处理 BOM 兼容问题。

完整版教学

一、CSV 看起来简单,实际有格式规则

CSV 表面上是用逗号分隔:

id,name
1,Alice
2,Bob

但真实 CSV 可以包含更复杂内容:

id,name,remark
1,Alice,"hello, world"
2,Bob,"line1
line2"

如果用:

line.split(",")

第一行 remark 里的逗号会被错误拆开,多行字段也会彻底乱掉。CSV 有引号、转义、换行等规则,所以应该交给 csv 模块处理。

二、reader 和 writer 适合按位置处理

csv.reader 每次返回一行列表:

import csv

with open("users.csv", "r", encoding="utf-8", newline="") as f:
    reader = csv.reader(f)
    header = next(reader)
    for row in reader:
        user_id = row[0]
        name = row[1]
        print(user_id, name)

这种方式适合列很少、位置固定、处理逻辑简单的场景。

写入时:

with open("users.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["id", "name"])
    writer.writerows([
        [1, "Alice"],
        [2, "Bob"],
    ])

csv.writer 会自动处理必要的引号和转义,不需要自己拼接字符串。

三、DictReader 和 DictWriter 适合按列名处理

当 CSV 有表头时,DictReader 更可读:

with open("users.csv", "r", encoding="utf-8", newline="") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row["id"], row["name"])

写入字典:

fields = ["id", "name"]

with open("users.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=fields)
    writer.writeheader()
    writer.writerow({"id": 1, "name": "Alice"})

它的好处是列顺序变化时更不容易写错,代码语义也清楚。缺点是比列表方式稍微多一点开销,不过大多数业务场景完全可以接受。

四、newline 参数为什么经常被问

官方文档建议用 newline="" 打开 CSV 文件。原因是文本文件对象本身可能处理换行,而 CSV 模块也要处理换行。如果两层都插手,可能出现额外空行或解析异常。

典型写法是:

open("data.csv", "w", encoding="utf-8", newline="")

这不是玄学,而是把 CSV 格式内的换行规则交给 csv 模块统一管理。

五、编码和 Excel 兼容问题

如果 CSV 面向程序之间交换,通常用 UTF-8:

encoding="utf-8"

如果要给某些版本的 Excel 直接打开,中文乱码时可能需要:

encoding="utf-8-sig"

utf-8-sig 会处理 UTF-8 BOM。它不是 CSV 标准本身的问题,而是某些工具识别编码的习惯问题。面试时可以提到,但不要把它当成所有 CSV 的默认选择。

六、常见误区与追问

易错点:CSV 不是“按逗号 split”。引号、逗号、换行、转义、编码和 Excel 兼容都会让手写解析很快失控。

  • 误区:CSV 行可以直接用 line.split(",") 解析。 字段里可能包含逗号、双引号或换行,例如 "Tom, Jr." 是一个字段,手写 split 会把它拆坏。
  • 追问:为什么打开 CSV 常写 newline=""csv 模块自己处理换行规则,避免文本层自动换行转换和 csv 写入换行叠加,尤其在 Windows 上可能出现空行。
  • 误区:readerDictReader 只是写法偏好。 reader 按位置取字段,适合列顺序稳定的简单数据;DictReader 按列名取字段,更适合可读性和列顺序变化。
  • 追问:Excel 打开中文 CSV 乱码怎么处理? 常见做法是使用 utf-8-sig 写入带 BOM 的 UTF-8 文件,让部分 Excel 版本更容易识别编码。
  • 误区:CSV 能可靠表达复杂嵌套结构。 CSV 更适合二维表;嵌套对象、数组、层级配置更适合 JSON、Parquet 或数据库表设计。
  • 追问:写 CSV 时为什么要显式 fieldnames? DictWriter 需要知道列顺序和允许的列集合,显式 fieldnames 可以稳定输出结构,也能暴露多余字段或缺失字段问题。

七、加强记忆

CSV 不是简单的逗号切割,而是一种有引号、转义和换行规则的文本格式。读写用 csv.readercsv.writer,有表头时用 DictReaderDictWriter;打开文件显式指定编码,并记住 newline="",让 CSV 模块自己处理格式内的换行。