Skip to content

23|CSV 数据

CSV(Comma-Separated Values)是最简单的表格数据格式。每行是一条记录,字段用逗号分隔。Excel、数据库导出、日志分析——这些场景都常见 CSV。

Python 标准库的 csv 模块提供了读写 CSV 的能力。

一、读取 CSV

python
import csv
from pathlib import Path

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

users.csv

csv
name,age,city
Alice,25,Beijing
Bob,30,Shanghai
Charlie,28,Guangzhou

输出:

python
['name', 'age', 'city']
['Alice', '25', 'Beijing']
['Bob', '30', 'Shanghai']
['Charlie', '28', 'Guangzhou']

csv.reader 返回的行是字符串列表。数字也是字符串,需要手动转换。

newline="" 参数:CSV 模块的文档要求打开文件时指定 newline="",否则在某些平台上可能出现空行问题。

二、DictReader

按表头把每行变成字典,比按索引访问更清晰:

python
import csv
from pathlib import Path

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

输出:

python
{'name': 'Alice', 'age': '25', 'city': 'Beijing'}
{'name': 'Bob', 'age': '30', 'city': 'Shanghai'}

DictReader 用第一行作为字段名。如果 CSV 没有表头,可以手动指定:

python
reader = csv.DictReader(f, fieldnames=["name", "age", "city"])

三、写入 CSV

python
import csv
from pathlib import Path

rows = [
    ["name", "age", "city"],
    ["Alice", 25, "Beijing"],
    ["Bob", 30, "Shanghai"],
]

with Path("output.csv").open("w", encoding="utf-8", newline="") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

writerow() 写一行,writerows() 写多行。

DictWriter:

python
import csv
from pathlib import Path

fieldnames = ["name", "age", "city"]
rows = [
    {"name": "Alice", "age": 25, "city": "Beijing"},
    {"name": "Bob", "age": 30, "city": "Shanghai"},
]

with Path("output.csv").open("w", encoding="utf-8", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(rows)

四、处理特殊字符

字段内容包含逗号或换行时,CSV 会用引号包裹:

csv
name,description
Alice,"Has a cat, a dog, and a bird"
Bob,"Multi
line
description"

csv 模块会自动处理引号的转义和解析,不需要手动处理。

自定义分隔符(TSV 格式):

python
# 读取 TSV(制表符分隔)
reader = csv.reader(f, delimiter="\t")

# 写入 TSV
writer = csv.writer(f, delimiter="\t")

五、常见陷阱

数字是字符串

CSV 没有类型信息,所有字段都是字符串:

python
reader = csv.DictReader(f)
for row in reader:
    age = int(row["age"])   # 手动转换

编码问题

CSV 文件可能是 GBK 编码(尤其 Windows 中文环境生成的文件):

python
# 尝试不同编码
with open("data.csv", "r", encoding="utf-8") as f:
    ...

with open("data.csv", "r", encoding="gbk") as f:
    ...

空行

csv.reader 默认会跳过空行,但某些情况下(如空字段被当成空字符串)需要额外处理。

六、CSV 与列表/字典的转换

python
import csv
from io import StringIO

# CSV 字符串 → 字典列表
csv_text = "name,age\nAlice,25\nBob,30"
reader = csv.DictReader(StringIO(csv_text))
records = list(reader)
# [{'name': 'Alice', 'age': '25'}, {'name': 'Bob', 'age': '30'}]

# 字典列表 → CSV 字符串
output = StringIO()
writer = csv.DictWriter(output, fieldnames=["name", "age"])
writer.writeheader()
writer.writerows(records)
print(output.getvalue())

StringIO 把字符串当成文件对象,适合在内存中处理 CSV 而不落盘。

记忆锚点csv.reader 返回字符串列表,csv.DictReader 返回字典;newline="" 是 CSV 的固定要求;writerow() 写一行,writerows() 写多行;CSV 所有字段都是字符串,数字需要手动转换;TSV 用 delimiter="\t"StringIO 在内存中处理 CSV。