Python中使用csv.DictWriter写入Unicode的最优方法及报错解决
这个UnicodeEncodeError问题我太熟悉了!本质是csv模块默认用ASCII编码写入,而你的数据里有像\xa0(非断空格)这种非ASCII字符,ASCII编码根本处理不了,所以报错了。下面分Python版本给你最实用的解决方案:
处理csv.DictWriter写入Unicode的最佳方式
Python 2.x 解决方案
Python 2的csv模块对Unicode确实不太友好,得稍微折腾一下,有两种常用方法:
方法1:手动编码Unicode字符串
先把Unicode字符串转成UTF-8字节串,再配合codecs.open以UTF-8编码打开文件。假设你的字段名对应数据结构如下,示例代码:
import csv import codecs # 请根据你的实际数据列调整字段名 fieldnames = ['id', 'name', 'dob', 'category', 'join_date', 'role', 'year', 'code1', 'code2', 'dept', 'empty_col', 'number'] # 用codecs以UTF-8编码打开输出文件 with codecs.open('output.csv', 'w', encoding='utf-8') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() # 遍历数据,先清理换行和非断空格,再编码写入 for row in row_all: # 你的row_all每个元素是包含列表的元组,所以取row[0] cleaned_data = [elem.strip().replace(u'\xa0', u' ') for elem in row[0]] # 把列表转成字典,并将Unicode转为UTF-8字节串 row_dict = {fieldnames[i]: val.encode('utf-8') for i, val in enumerate(cleaned_data)} writer.writerow(row_dict)
方法2:使用官方推荐的自定义UnicodeWriter类
这是Python官方文档给出的专门处理Unicode写入CSV的方案,稳定性更好:
import csv, codecs, cStringIO class UnicodeWriter: """专门处理Unicode的CSV写入器,支持指定编码""" def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): self.queue = cStringIO.StringIO() self.writer = csv.writer(self.queue, dialect=dialect, **kwds) self.stream = f self.encoder = codecs.getincrementalencoder(encoding)() def writerow(self, row): # 先将Unicode转成UTF-8再写入队列 self.writer.writerow([s.encode("utf-8") if isinstance(s, unicode) else s for s in row]) data = self.queue.getvalue() data = data.decode("utf-8") data = self.encoder.encode(data) self.stream.write(data) self.queue.truncate(0) def writerows(self, rows): for row in rows: self.writerow(row) # 使用示例 with open('output.csv', 'wb') as f: # Python2中需用二进制模式打开 writer = UnicodeWriter(f) writer.writerow(fieldnames) # 写入表头 for row in row_all: cleaned_data = [elem.strip().replace(u'\xa0', u' ') for elem in row[0]] writer.writerow(cleaned_data)
Python 3.x 解决方案
Python 3的csv模块原生支持Unicode,处理起来简单太多:
- 打开文件时指定
encoding='utf-8',同时设置newline=''避免生成额外空行 - 直接写入Unicode字符串就行
示例代码:
import csv fieldnames = ['id', 'name', 'dob', 'category', 'join_date', 'role', 'year', 'code1', 'code2', 'dept', 'empty_col', 'number'] # 注意newline=''是csv模块官方推荐的写法 with open('output.csv', 'w', encoding='utf-8', newline='') as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() for row in row_all: cleaned_data = [elem.strip().replace('\xa0', ' ') for elem in row[0]] row_dict = {fieldnames[i]: val for i, val in enumerate(cleaned_data)} writer.writerow(row_dict)
额外小提示
- 如果你不需要保留
\xa0(非断空格),用replace替换成普通空格能让数据更整洁 - 一定要确保字段名和数据的列数完全对应,不然会出现字段不匹配的问题
内容的提问来源于stack exchange,提问作者Alhpa Delta
相关产品推荐
相关产品推荐

