处理表格数据时,CSV几乎是最通用的交换格式,Excel、数据库导出工具、各类数据分析平台都认它。很多初学者图省事,直接用open加字符串拼接的方式写CSV,比如f.write(",".join(row) + "\n"),一旦某个字段本身含有逗号、引号或者换行符,整行数据立刻错位,Excel打开后列全乱了。正确的做法是使用Python内置的csv模块,它遵循RFC 4180标准,会自动处理转义、引号包裹等细节,完全不需要手动拼接。

csv.writer基础用法:写入列表数据
csv模块的核心思路是:先用open打开一个文件对象,再把这个文件对象交给csv.writer,得到一个writer对象,之后调用它的writerow方法逐行写入。每一行数据用列表表示,writer会自动在字段之间插入逗号,并在文件末尾加上换行符。
import csv
# 表头数据
headers = ["姓名", "年龄", "城市"]
# 两行示例数据
rows = [
["张三", 28, "北京"],
["李四", 35, "上海"]
]
# newline="" 是关键,后面会解释原因
with open("people.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(headers) # 写入表头
writer.writerows(rows) # 批量写入多行
这里有两个容易被忽略的细节。第一个是newline=""code>参数。Windows系统下,文本模式打开的文件会把换行符自动转换成回车加换行,而csv.writer自己也会追加换行,两者叠加就会在每行数据之间产生空行,Excel打开后每隔一行就是一个空白行,看起来非常难受。加上newline=""就禁用了系统的换行转换,输出的文件干净利落。
第二个细节是writerow和writerows的区别。writerow一次写一行,接收一个列表参数,适合逐条写入的场景,比如实时记录日志或边采集边写入。writerows一次接收一个可迭代对象,内部循环调用writerow,适合数据已经全部准备好、一次性批量落盘的场景,代码更简洁,也是批量写入的首选。
字段含逗号或引号怎么办:quoting参数与自动转义
CSV用逗号分隔字段,那字段内容本身有逗号怎么办?标准做法是用双引号把这个字段包裹起来,如果内容里还有双引号,就把引号翻倍。这些规则csv.writer全部自动处理,这也是它比手动拼接可靠的根本原因。
import csv
rows = [
["产品", "描述", "价格"],
# 描述字段包含逗号和双引号
["手机", '5.5寸屏, 支持"快充"', 2999],
["笔记本", "14寸, 轻薄本", 4599]
]
with open("products.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f, quoting=csv.QUOTE_MINIMAL)
writer.writerows(rows)
上面代码输出的文件中,含逗号的描述字段会被自动加上双引号,含双引号的地方会变成两个双引号。Excel和pandas读取时都能正确还原,数据不会错位。quoting参数有四个可选值,行为差异如下表所示:
| 取值 | 行为说明 | 适用场景 |
|---|---|---|
| csv.QUOTE_MINIMAL | 默认值,仅在字段包含逗号、引号、换行符时才加引号包裹 | 绝大多数场景,文件体积最小 |
| csv.QUOTE_ALL | 所有字段都用双引号包裹 | 某些严格要求全引号格式的导入工具 |
| csv.QUOTE_NONNUMERIC | 非数字字段加引号,数字不加 | 配合读取时的自动类型转换 |
| csv.QUOTE_NONE | 不加引号,遇到特殊字符会报错,需配合escapechar指定转义符 | 特殊定界格式,一般不用 |
另外提一下delimiter参数,它默认是逗号,如果你的目标格式其实是制表符分隔(TSV)或者分号分隔(某些欧洲地区Excel默认用分号),改成delimiter="\t"或delimiter=";"即可,其他逻辑完全不变。这个参数和quoting可以同时使用。
中文乱码与字典写入:两个高频实战问题
写入中文后用Excel打开全是乱码,是中文环境下最常见的报障之一。根源在于Excel识别UTF-8文件时依赖BOM头,而普通的utf-8编码不带BOM。解决办法有两个:一是把编码改成utf-8-sig,Python会在文件开头写入BOM,Excel就能正确识别;二是如果只需要在Windows的Excel里看,可以用gbk编码,但文件传到Mac或Linux上就会出问题,通用性差,不推荐。
import csv
rows = [
["姓名", "部门"],
["张三", "研发部"],
["李四", "市场部"]
]
# utf-8-sig 会写入BOM头,Excel打开不乱码
with open("staff.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
writer.writerows(rows)
当数据以字典形式存在时,用csv.DictWriter更顺手。它通过fieldnames指定列的顺序,写入时直接传字典,列名和数据的对应关系一目了然,不用担心列表顺序写错。写完表头记得调用writeheader,这是新手经常忘记的一步。
import csv
staff = [
{"name": "张三", "dept": "研发部", "salary": 15000},
{"name": "李四", "dept": "市场部", "salary": 12000}
]
with open("staff2.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=["name", "dept", "salary"])
writer.writeheader() # 写入表头,别漏掉
writer.writerows(staff)
最后一个常见需求是追加写入,比如定时任务每次把新数据追加到已有文件末尾。只需把打开模式从"w"改成"a"即可。要注意的是追加模式不会帮你补表头,需要自己判断文件是否为空再决定是否写入表头。如果数据量大、还需要做筛选聚合等处理,也可以改用pandas的to_csv方法,一行代码搞定,代价是多装一个依赖。对于纯写入场景,标准库csv模块轻量、零依赖,依然是首选方案。
Python写入CSVcsv.writer逗号分隔数据修改时间:2026-09-09 03:36:34