作者:许灼灼
成绩单班主任用Excel就能打开?Python写CSV文件
上次课我们刚给程序装上"安全气囊"——try/except 让它不再动不动就崩溃。小张高兴地把改好的成绩管理系统发给班主任看。
班主任打开程序,输入了几个成绩,"不错,挺方便的。"
然后班主任问了一句:"能不能把成绩导出成表格?我想在 Excel 里统计平均分、排个名次什么的。"
小张愣住了。他存的成绩文件 成绩.txt 长这样:
张三 90 李四 85 王五 78
Excel 打开——全是乱的,人和分数混在一起,根本没法统计分析。
"老师,.txt Excel 打不开啊,怎么办?"
"当然有办法。"老师说,"今天教你一个新格式——CSV。它本质上是文本文件,但 Excel 能完美打开。"
什么是 CSV:三个字母拆开看
CSV 的全称是 Comma-Separated Values,翻译过来就是"用逗号分隔的值"。
听起来高级?其实就是把表格的每一行,用逗号把数据连起来:
张三,90 李四,85 王五,78
这就是 CSV。就这么多。
你把这行字写进一个 .csv 文件,双击打开,Excel 会自动把它识别成表格:
CSV = 纯文本 + 逗号分隔 + Excel 能认。
它不像 .xlsx 那样带格式、带公式、带颜色——CSV 就是最朴素的表格,只有数据,没有花哨。
为什么用 CSV?
| |
|---|
| |
| |
| |
| Python 内置 csv 模块,不用安装任何东西 |
一句话:TXT 是写给程序看的,CSV 是写给人和 Excel 一起看的。
写入 CSV:三步搞定
Python 写 CSV,用的是内置的 csv 模块。跟写 txt 差不多,只是中间多了一层"翻译"。
import csv # 第1步:打开文件(跟以前一样) with open("成绩.csv", "w", newline="", encoding="utf-8-sig") as f: # 第2步:创建一个"写手" writer = csv.writer(f) # 第3步:一行一行往里写 writer.writerow(["张三", 90]) writer.writerow(["李四", 85]) writer.writerow(["王五", 78]) 拆开看每一行:
第 1 步:open("成绩.csv", "w", newline="", encoding="utf-8-sig")
"w"newline="":这个很重要——不写它,Windows 上每行之间会多一个空行。原因不用深究,记住要写就行encoding="utf-8-sig":编码。utf-8-sig 比普通 utf-8 多了一个"标记",告诉 Excel "我是中文",否则 Excel 打开中文会乱码
第 2 步:csv.writer(f)
创建了一个"写手"——它知道怎么把列表变成 CSV 格式。给它一个列表,它自动加逗号、处理引号。
第 3 步:writer.writerow(["张三", 90])
writerow = write row,写一行。参数是一个列表,每个元素是一列的内容。
这里用列表而不用字符串:["张三", 90] 而不是 "张三,90"——因为 writer 帮你处理了逗号、引号这些边界情况。如果名字本身带逗号(比如"张三, Jr."),你自己拼字符串就傻了,writer 会自动处理。
实战:把成绩管理系统里的数据存成 CSV
之前成绩管理系统里的成绩是一个字典:
scores = {"张三": 90, "李四": 85, "王五": 78} 把它导出成 CSV:
import csv scores = {"张三": 90, "李四": 85, "王五": 78} with open("成绩.csv", "w", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) # 先写表头(第一行是列名) writer.writerow(["姓名", "成绩"]) # 再把字典里的每一对写进去 for name, score in scores.items(): writer.writerow([name, score]) print("导出成功!用 Excel 打开 成绩.csv 看看") 运行后,桌面上出现 成绩.csv,双击——Excel 打开,姓名一列、成绩一列,完美。
写入多列:不止两列
CSV 不止能写两列。想写几列就写几列,只要每行的列表长度一致:
import csv students = [ ["张三", "1班", 90, 88, 85], ["李四", "2班", 78, 92, 80], ["王五", "1班", 85, 76, 90], ] with open("学生成绩表.csv", "w", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) # 表头 writer.writerow(["姓名", "班级", "语文", "数学", "英语"]) # 数据行 for row in students: writer.writerow(row) Excel 打开就是一张完整的成绩单,三科成绩一目了然。
读取 CSV:把 Excel 的数据读进 Python
写完了能读吗?当然能。用 csv.reader:
import csv with open("成绩.csv", "r", encoding="utf-8-sig") as f: reader = csv.reader(f) for row in reader: print(row) 运行结果:
['姓名', '成绩'] ['张三', '90'] ['李四', '85'] ['王五', '78']
注意:csv.reader 读出来的全是字符串。'90' 是字符串不是数字——如果要做计算,还得用 int() 转一下。
跳过表头:next() 函数
通常第一行是表头("姓名"、"成绩"),你不想把它当数据处理。用 next() 跳过:
import csv with open("成绩.csv", "r", encoding="utf-8-sig") as f: reader = csv.reader(f) # 跳过第一行(表头) header = next(reader) scores = {} for row in reader: name = row[0] # 第1列:姓名 score = int(row[1]) # 第2列:成绩,转成整数 scores[name] = score print(scores) # {'张三': 90, '李四': 85, '王五': 78} next(reader) 就是"读下一行,然后扔掉"——这里的"下一行"刚好是表头,跳过。
写入/读取对照表
| | |
|---|
| csv.writer(f) | |
| writer.writerow([列1, 列2, ...]) | |
| writer.writerows([行1列表, 行2列表, ...]) | |
| csv.reader(f) | |
| next(reader) | |
| for row in reader: | |
| row[0] | |
重要参数:
| | |
|---|
newline="" | "" | |
encoding | utf-8-sig | |
| "w" | |
Excel 表格类比
把 CSV 想象成一个"通用表格格式"——
| |
|---|
| |
csv.writer | |
writer.writerow(["张三", 90]) | |
.csv | |
| |
csv.reader | |
for row in reader | |
.txt 文件就像一本乱七八糟的草稿本——你自己能看懂,但别人看着费劲。
.csv 文件就像一张填好的表格——谁拿过来都能用,Excel 打开就是整齐的行列。
之前用 .txt 存数据,是自己跟程序说话;现在用 .csv,是让你的程序跟整个世界对话。
5 个常见坑
坑1:忘了 newline=""
# ❌ 漏了 newline="" with open("成绩.csv", "w", encoding="utf-8-sig") as f: writer = csv.writer(f) writer.writerow(["张三", 90]) 在 Windows 上,打开的 CSV 文件每两行之间会多一个空行——张三和 90 之间空一行,下一行又是空的。看着像 bug,其实就是缺了 newline=""。
坑2:Excel 打开中文乱码
# ❌ 用了普通 utf-8 with open("成绩.csv", "w", encoding="utf-8") as f: ... 用 Excel 打开,中文全是乱码。换成 utf-8-sig 就好了。-sig 在文件开头加了一个看不见的标记(BOM),这个标记就是告诉 Excel "里面是中文"。
坑3:reader 读出来全是字符串
import csv with open("成绩.csv", "r", encoding="utf-8-sig") as f: reader = csv.reader(f) for row in reader: score = row[1] # '90',这是字符串! print(score * 2) # '9090' 而不是 180 CSV 存的是纯文本,读回来就是字符串。如果要做数学运算,记得 int(row[1]) 或 float(row[1])。
坑4:writerow 的参数不是列表
# ❌ 传了多个参数 writer.writerow("张三", 90) # 报错! # ❌ 传了字符串 writer.writerow("张三,90") # 不会报错,但变成一列:"张,三,,,9,0",完全乱了 # ✅ 传列表 writer.writerow(["张三", 90]) writerow() 只接受一个参数——一个列表。列表里每一项是一列。
坑5:追加模式忘了表头
# ❌ 追加数据时又写了一行表头 with open("成绩.csv", "a", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) writer.writerow(["姓名", "成绩"]) # 表头又写了一遍! writer.writerow(["赵六", 92]) 用 "a" 追加时,文件已经有表头了,别再写一遍。只有 "w" 模式新建文件时才需要写表头。
练一练
第1题:导出成绩字典
把下面的字典导出成 CSV 文件 成绩单.csv,包含表头"姓名"和"成绩":
scores = { "小明": 92, "小红": 88, "小刚": 76, "小丽": 95, "小华": 81, } 第2题:读取并统计
从 成绩单.csv 里读取所有成绩,计算:
# 提示:用 csv.reader 逐行读取 # 注意:读出来的成绩是字符串,要用 int() 转换
第3题:成绩管理系统存盘升级
把你之前写的成绩管理系统升级一下:
- 程序启动时,尝试从
学生成绩.csv 加载数据(用 try/except 处理文件不存在) - 用 CSV 格式(表头:姓名、成绩),方便班主任用 Excel 打开
# 提示:封装 save_data(scores_dict) 和 load_data() 两个函数 # load_data 用 try/except FileNotFoundError # save_data 用 with open + csv.writer
小结
| |
|---|
| |
csv.writer(f) | |
writer.writerow(list) | |
csv.reader(f) | |
next(reader) | |
newline="" | |
utf-8-sig | |
| |
能用 txt 解决问题的时候用 txt;需要给别人看、要在 Excel 里分析数据的时候,用 CSV。
下一篇,我们要把这个模块学的所有技能串起来——文件读写 + with open + 追记 + 异常处理 + CSV,做一个完整的迷你日记本 v1.0。从启动到退出,每一步都稳如磐石。