🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

【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` 时有两个注意事项:

  1. 初始化 `csv.DictWriter()` 时,需要传递 `fieldnames`(标题列表)。
  2. 在写入数据之前,需要用 `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 时就几乎不会遇到什么困难了。无论是分析从网站下载的数据,还是一次性将大量数据注册到系统中,应用的范围都因你的想法而无限广阔。

编程的进步诀窍,就是这样一步步积累“成功运行!”的体验。如果本文能为你的这段旅程提供一点帮助,我将感到无比欣慰。

下一步

在 Web 开发中,和 CSV 一样常用的数据格式是“JSON”。对于 API 对接等更高级的开发来说,这是必备的知识。在下一篇文章中掌握它,让自己更上一层楼吧!

如何使用 json 模块处理 JSON 数据