【Python】csv 模块完全指南!详解初学者读写 CSV 时的常见陷阱
要在电脑上通过命令提示符或 PowerShell 运行 Python,需要先下载并安装 Python。
如果你还没有安装,请参考Python安装与开发环境配置一文来完成安装。
“我想在编程中处理 CSV 文件,但不知道从何下手…”
你好!我是本站的管理员,几个月前也和大家一样是个“前”初学者。凭借着 AI 的帮助,我用一个半月的时间独立创建了两个网站,以我的经验来说,CSV 文件操作是 Web 开发中不可或不可缺的一项技能,而且非常方便!
实际上,当我在制作管理联系表单数据或批量上传商品列表等功能时,CSV 的知识帮了我大忙。
在本文中,我将根据我的实际经验(以及许多失败的教训……),用全世界最易懂的方式,解说如何使用 Python 的 `csv` 模块随心所欲地读写 CSV 文件。我会尽量避免使用专业术语。读完本文时,你应该已经成为一名 CSV 大师了!
准备活动:创建用于操作的 CSV 示例文件
首先,我们来准备一个用于练习的 CSV 文件。请复制以下内容,并以 `members.csv` 的名称保存在你的电脑上。重点是要以UTF-8编码保存。(使用记事本保存时,应该有编码选项。)
此文件模拟了一个虚构网站的会员列表。
id,name,email
1,张伟,zhang.wei@example.com
2,李静,li.jing@example.com
3,王磊,wang.lei@example.com
基础入门:尝试读取 CSV 文件 (`csv.reader`)
首先要做的是用 Python 读取 CSV 文件的内容。让我们来读取刚才创建的 `members.csv` 文件,并将其内容显示在控制台中。
好的,我们直接看代码!请复制并执行它。最简单的方法是在 `members.csv` 所在的目录中创建一个 Python 文件并执行。
<!-- 经过 HTML 转义的 Python 代码 -->
import csv
# --- 我遇到的坑点①:一定要指定字符编码!---
# 在 Windows 环境中,如果不进行任何设置,有时会尝试用 Shift_JIS 打开并导致错误。
# 最好养成习惯,像护身符一样加上 `encoding='utf-8'`。
with open('members.csv', mode='r', encoding='utf-8') as f:
# 将文件传递给 csv.reader,它会返回一个能解析 CSV 的 reader 对象
reader = csv.reader(f)
# 可以用循环逐行处理
for row in reader:
print(row)
# 执行结果:
# ['id', 'name', 'email']
# ['1', '张伟', 'zhang.wei@example.com']
# ['2', '李静', 'li.jing@example.com']
# ['3', '王磊', 'wang.lei@example.com']
怎么样?终端里显示 CSV 的内容了吗?
值得注意的一点是,每一行都被读取为一个列表(就是用`[]`括起来的东西)。像 `['1', '张伟', 'zhang.wei@example.com']` 这样,用逗号分隔的数据成为了列表中的各个元素。
简单解说:`with open(...) as f:` 是什么?
这是处理文件时的“标准做法”。这样写的话,当代码块 `with` 执行完毕后,Python 会自动关闭文件。如果忘记关闭文件,可能会导致内存泄漏等意想不到的问题,所以一定要使用 `with`!
【我的失败谈①】乱码地狱与`encoding`
我第一次这样做时,尤其是在 Windows 电脑上,控制台里满是看不懂的符号(俗称“豆腐块”)。原因是字符编码。我们必须告诉电脑文件是用哪种语言规则(编码)编写的,否则它无法正确读取。
解决方法是在 `open()` 函数的参数中添加 `encoding='utf-8'`。`UTF-8` 是世界通用的标准字符编码,使用它基本上就能解决问题。在 Web 世界里,这是必备知识,所以养成习惯吧!
基础进阶:尝试写入新的 CSV 文件 (`csv.writer`)
接下来是数据写入。我们来尝试将 Python 中创建的列表数据保存为一个新的 CSV 文件。例如,可以想象成将新的会员数据写入一个名为 `new_members.csv` 的文件。
<!-- 经过 HTML 转义的 Python 代码 -->
import csv
# 想要写入的数据(列表的列表)
new_data = [
['4', '刘洋', 'liu.yang@example.com'],
['5', '陈好', 'chen.hao@example.com']
]
# --- 我遇到的坑点②:神秘的空行要用 newline='' 解决 ---
# mode='w' 是写入模式。如果文件不存在,会自动创建。
# 如果不指定 newline='',在 Windows 中每隔一行就会出现一个神秘的空行!
with open('new_members.csv', mode='w', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
# 如果只想写入一行,使用 writerow
writer.writerow(['id', 'name', 'email']) # 标题行
# 如果想一次性写入多行,使用 writerows
writer.writerows(new_data)
print('已创建 new_members.csv!')
执行此代码后,在同一目录下应该会生成一个名为 `new_members.csv` 的文件。打开看看,数据是不是已经正确写入了?
【我的失败谈②】你是谁?!神秘的空行与`newline=''`
这也是一个让我耗费了半天时间的问题。试试把上面代码中的 `newline=''` 去掉,然后在 Windows 上执行。怎么样?CSV 文件是不是每隔一行就被可恶的空行填满了?
这是一个很常见的陷阱,原因是不同操作系统对换行符的处理方式不同。详细的解释太长我就省略了(我自己问了 AI 也是“哦,原来如此,但还是不懂!”的感觉),但解决方法只有一个。
写入 CSV 文件时,一定要在 `open()` 中加上 `newline=''`!
这是 Python 官方文档中也写明的超重要规则:“如果使用 csv 模块,应始终指定此参数”。像咒语一样记住它吧。
应用篇①:用字典处理,代码可读性瞬间封神 (`DictReader` & `DictWriter`)
使用基本的 `reader` 时,我们需要通过索引号来管理数据,比如 `row[1]` 或 `row[2]`。当列数增多时,你就会开始犯迷糊:“哎,邮箱是第几列来着…?”
这时 `DictReader` 就登场了!用它,你可以将每一行数据作为“字典”来获取。也就是说,你可以通过标题名来访问数据,比如 `row['name']` 或 `row['email']`。简直是天才设计!
读取: `DictReader`
<!-- 经过 HTML 转义的 Python 代码 -->
import csv
with open('members.csv', mode='r', encoding='utf-8') as f:
# 只需使用 DictReader!很简单!
reader = csv.DictReader(f)
for row in reader:
# 可以用 'name' 键访问姓名,用 'email' 键访问邮箱!
print(f"姓名: {row['name']}, 邮箱: {row['email']}")
# 执行结果:
# 姓名: 张伟, 邮箱: zhang.wei@example.com
# 姓名: 李静, 邮箱: li.jing@example.com
# 姓名: 王磊, 邮箱: wang.lei@example.com
怎么样?`row['name']` 是不是比 `row[1]` 清晰易懂多了?这样一来,即使以后再看代码,也能一目了然地知道在做什么。
写入: `DictWriter`
既然能用字典读取,当然也希望能用字典写入。没问题,有 `DictWriter`。只要准备一个字典列表,就能把它写入 CSV 文件。
<!-- 经过 HTML 转义的 Python 代码 -->
import csv
# 准备一个字典列表作为数据
dict_data = [
{'id': '6', 'name': '赵明', 'email': 'zhao.ming@example.com'},
{'id': '7', 'name': '周敏', 'email': 'zhou.min@example.com'}
]
# 标题列表(重要!)
fieldnames = ['id', 'name', 'email']
with open('dict_members.csv', mode='w', encoding='utf-8', newline='') as f:
# 将文件和标题(fieldnames)传递给 DictWriter
writer = csv.DictWriter(f, fieldnames=fieldnames)
# 别忘了先写入标题行!
writer.writeheader()
# 一次性写入整个字典列表
writer.writerows(dict_data)
print('已创建 dict_members.csv!')
使用 `DictWriter` 时有两个注意事项:
- 初始化 `csv.DictWriter()` 时,需要传递 `fieldnames`(标题列表)。
- 在写入数据之前,需要用 `writer.writeheader()` 写入标题行。
如果忘了这些,就无法正确写入,请多加注意!(我当然也犯过这个错)
应用篇②:向现有 CSV 文件追加数据
“每次收到新的联系表单,都想把新的会员信息添加到列表中。” 这种时候,只需以“追加模式”打开文件即可。
方法超级简单,就是把 `open()` 的 `mode` 从 `'w'` (write) 改成 `'a'` (append)。
<!-- 经过 HTML 转义的 Python 代码 -->
import csv
# 想要追加的新会员数据
new_member = ['8', '黄琳', 'huang.lin@example.com']
# 只需将 mode 改为 'a' (append)!
# 因为是追加,别忘了 newline='' 和 encoding='utf-8'。
with open('members.csv', mode='a', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
writer.writerow(new_member)
print('已向 members.csv 追加数据!')
执行此代码后,再次打开 `members.csv` 文件看看。你会发现黄琳的信息已经被添加到了文件末尾。如果用 `DictWriter` 追加数据,注意不要调用 `writeheader()`,否则每次追加都会多一个标题行。
【亲身体验】在浏览器中玩转 CSV!
好了,到目前为止我们看了很多代码。但说到底,自己动手运行、修改才是最好的学习捷径。
因此,这次我用“PyScript”这项能在浏览器中运行 Python 的神奇技术,准备了一个可以实时操作 CSV 数据的交互式演示!
请将下面的 HTML 代码完整复制,并以 `csv_test.html` 之类的名称保存在你的电脑上。然后,用浏览器打开该文件。仅需如此,你的浏览器就摇身一变,成了一个 CSV 编辑器!
<!-- 经过 HTML 转义的 HTML 代码 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python CSV 模块交互式演示</title>
<!-- 加载 PyScript -->
<link rel="stylesheet" href="https://pyscript.net/releases/2024.1.1/core.css" />
<script type="module" src="https://pyscript.net/releases/2024.1.1/core.js"></script>
<!-- 简单样式 -->
<style>
body { font-family: sans-serif; background-color: #202124; color: #e8eaed; padding: 2em; line-height: 1.6; }
h1, h2 { color: #8ab4f8; }
textarea, button {
border: 1px solid #5f6368;
background-color: #3c4043;
color: #e8eaed;
border-radius: 4px;
padding: 0.5em 1em;
}
textarea { width: 100%; height: 150px; margin-bottom: 1em; font-family: monospace; }
button { cursor: pointer; margin-right: 1em; }
button:hover { background-color: #5f6368; }
table { border-collapse: collapse; width: 100%; margin-top: 1em; }
th, td { border: 1px solid #5f6368; padding: 8px; text-align: left; }
th { background-color: #3c4043; }
pre { background-color: #1e1e1e; padding: 1em; border-radius: 4px; white-space: pre-wrap; }
</style>
</head>
<body>
<h1>在浏览器中体验 Python CSV 模块!</h1>
<p>在下方的文本区域输入或编辑 CSV 数据,然后点击“加载CSV并显示为表格”按钮。</p>
<textarea id="csv-input">姓名,年龄,城市
张伟,32,东京
李静,28,大阪
王磊,45,福冈</textarea>
<button py-click="read_csv">加载CSV并显示为表格</button>
<h2>加载结果</h2>
<div id="table-output"></div>
<py-script>
# 下面的 Python 代码在浏览器中运行
import csv
import io # 用于将字符串当作文件处理的模块
from pyscript import document
def read_csv(*args, **kwargs):
# 从文本区域获取 CSV 数据
csv_data = document.querySelector("#csv-input").value
# 使用 io.StringIO 将字符串当作文件来处理
# 这样,就可以像从文件中读取一样使用 csv 模块了
csv_file = io.StringIO(csv_data)
# 用 csv.reader 读取
reader = csv.reader(csv_file)
# 生成 HTML 表格
html = "<table>"
try:
# 处理第一行(标题)
header = next(reader)
html += "<thead><tr>"
for col in header:
html += f"<th>{col}</th>"
html += "</tr></thead>"
# 处理第二行及之后的数据
html += "<tbody>"
for row in reader:
html += "<tr>"
for cell in row:
html += f"<td>{cell}</td>"
html += "</tr>"
html += "</tbody>"
except StopIteration:
# 处理数据为空的情况
html += "<tr><td>没有可用数据</td></tr>"
html += "</table>"
# 在 DIV 元素中显示结果
output_div = document.querySelector("#table-output")
output_div.innerHTML = html
</py-script>
</body>
</html>
随意修改文本区域中的内容并点击按钮试试看。你会发现,逗号分隔的文本被转换成了漂亮的表格。这就是 `csv` 模块的力量!请尽情地玩耍吧。
总结:你已经掌握 CSV 了!
辛苦了!虽然是一段漫长的旅程,但现在你已经完全掌握了使用 Python 操作 CSV 的基础和应用。最后,让我们回顾一下今天学到的最关键的要点。
- 读取: 基础用 `csv.reader`,如果想按列名处理则用 `csv.DictReader`。
- 写入: 基础用 `csv.writer`,如果想用字典写入则用 `csv.DictWriter`。
- 追加: 将 `open()` 的模式设为 `'a'`。
- 两大必记咒语: 读写时用 `encoding='utf-8'`,写入时用 `newline=''`。
只要掌握了这些,在实际工作中处理 CSV 时就几乎不会遇到什么困难了。无论是分析从网站下载的数据,还是一次性将大量数据注册到系统中,应用的范围都因你的想法而无限广阔。
编程的进步诀窍,就是这样一步步积累“成功运行!”的体验。如果本文能为你的这段旅程提供一点帮助,我将感到无比欣慰。
下一步
在 Web 开发中,和 CSV 一样常用的数据格式是“JSON”。对于 API 对接等更高级的开发来说,这是必备的知识。在下一篇文章中掌握它,让自己更上一层楼吧!
如何使用 json 模块处理 JSON 数据