我正在尝试用Unicode字符写出一个csv文件,所以我正在使用unicodecsv包。不幸的是,我仍然得到UnicodeDecodeErrors:
# -*- coding: utf-8 -*-
import codecs
import unicodecsv
raw_contents = 'He observes an “Oversized Gorilla” near Ashford'
encoded_contents = unicode(raw_contents, errors='replace')
with codecs.open('test.csv', 'w', 'UTF-8') as f:
w = unicodecsv.writer(f, encoding='UTF-8')
w.writerow(["1", encoded_contents])
这是追溯:
Traceback (most recent call last):
File "unicode_test.py", line 11, in <module>
w.writerow(["1", encoded_contents])
File "/Library/Python/2.7/site-packages/unicodecsv/__init__.py", line 83, in writerow
self.writer.writerow(_stringify_list(row, self.encoding, self.encoding_errors))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/codecs.py", line 691, in write
return self.writer.write(data)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/codecs.py", line 351, in write
data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xef in position 17: ordinal not in range(128)
我认为将它转换为Unicode就足够了,但似乎并非如此。我真的很想了解发生了什么,这样我就能更好地准备好在将来的其他项目中处理这些错误。
从回溯中看起来我可以像这样重现错误:
>>> raw_contents = 'He observes an “Oversized Gorilla” near Ashford'
>>> raw_contents.encode('UTF-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 15: ordinal not in range(128)
>>>
到目前为止,我认为我在Python 2.x中使用Unicode文本方面有一定的工作知识,但这让我感到很沮丧。
答案 0 :(得分:8)
您不使用codecs.open()
作为您的文件。 unicodecsv
包装csv
模块,该模块始终将字节字符串写入打开的文件对象。为了将该字节字符串写入由codecs.open()
返回的Unicode识别文件对象,它隐式地解码;这是UnicodeDecodeError
例外源自的地方。
使用二进制模式的文件:
with open('test.csv', 'wb') as f:
w = unicodecsv.writer(f, encoding='UTF-8')
w.writerow(["1", encoded_contents])
除非您的数据包含嵌入的换行符,否则二进制模式不是必需的,但csv
模块想要控制如何写入换行符以确保正确处理这些值。但是,不使用codecs.open()
是绝对必要的。
当您在字节字符串上调用.encode()
时会发生同样的事情;你已经在那里编码了数据,因此Python隐式解码以获取要编码的Unicode值。