Appearance
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。