Python2使用openpyxl转xlsm为CSV时遭遇UnicodeEncodeError问题
解决Python2中xlsm转CSV的UnicodeEncodeError问题
错误原因
- Python2的
csv模块原生不支持Unicode对象,默认会用ASCII编码处理字符串,遇到非ASCII字符(比如示例中的u'\xfa'、u'\xd1')就会抛出编码错误。 - 从Excel读取的列表包含多种非字符串类型(
datetime、None、布尔值、长整数等),这些类型无法直接被csv模块处理。
修正方案
需要先对每个单元格的值做类型转换和编码处理,再写入CSV:
1. 编写值转换函数
把所有非字符串类型统一转为字符串,并将Unicode编码为UTF-8格式的字节串:
def convert_value(value): if isinstance(value, unicode): # 将Unicode字符串编码为UTF-8的str return value.encode('utf-8') elif isinstance(value, datetime.datetime): # 将datetime转为指定格式的字符串 return value.strftime('%Y-%m-%d %H:%M:%S') elif value is None: # None转为空字符串 return '' elif isinstance(value, bool): # 布尔值转为对应的字符串,可根据需求调整 return 'SI' if value else 'NO' elif isinstance(value, (int, long)): # 整数/长整数转为字符串 return str(value) else: # 其他类型直接转为字符串 return str(value)
2. 完整修正代码
在读取行数据时应用转换函数,并且用二进制模式打开文件写入(避免编码冲突):
from openpyxl import load_workbook import csv import datetime excelFile = load_workbook('test.xlsm', data_only=True) currentSheet = excelFile.worksheets[0] def convert_value(value): if isinstance(value, unicode): return value.encode('utf-8') elif isinstance(value, datetime.datetime): return value.strftime('%Y-%m-%d %H:%M:%S') elif value is None: return '' elif isinstance(value, bool): return 'SI' if value else 'NO' elif isinstance(value, (int, long)): return str(value) else: return str(value) def iter_rows(currentSheet): for row in currentSheet.iter_rows(): yield [convert_value(cell.value) for cell in row] def listIntoCsv(data_list): # 用二进制模式打开文件,避免编码问题 with open('test.csv', 'wb') as f: write = csv.writer(f) write.writerows(data_list) finalList = list(iter_rows(currentSheet)) listIntoCsv(finalList)
关键说明
- 类型转换:确保所有数据都转为
csv模块能处理的字符串类型,同时处理了Unicode编码、日期、空值等特殊情况。 - 文件打开方式:使用
wb二进制模式写入,避免Python2中文本模式的编码自动转换干扰csv模块的处理。 - 编码统一:将所有Unicode字符串转为UTF-8编码的字节串,保证CSV文件支持多语言字符。
内容的提问来源于stack exchange,提问作者Jordi Lazo
相关产品推荐
相关产品推荐

