尝试在Python中将数据写入CSV时,我收到以下错误.
File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/csv.py", line 150, in writerows
UnicodeEncodeError: 'ascii' codec can't encode character u'\xd3' in position 0: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)
以下是我尝试写入CSV的字典示例:
{'Field1': 'Blah \xc3\x93 D\xc3\xa1blah', 'Field2': u'\xd3', 'Field3': u'Blah', 'Field4': u'D\xe1blah'}
Run Code Online (Sandbox Code Playgroud)
我知道你不能使用Python将unicode写入CSV,但是我无法弄清楚要转换的内容以及如何转换它.
编辑:这是我试过的. dictList是从另一个CSV中获取的词典列表.
WANTED_HEADERS = ['First Name',
'Last Name',
'Date',
'ID']
def utf8ify(d):
return dict((str(k).encode('utf-8'), str(v).encode('utf-8')) for k, v in d.iteritems())
def ListToCSVWithHeaders(data_list, output_file_name, headers):
output_file = open(output_file_name, 'w')
header_row = {}
to_append = []
for entry in data_list:
to_append.append(utf8ify(entry))
for key in entry.keys():
if key not in headers:
headers.append(key)
print 'KEY APPENDED: ' + key
for header in headers:
header_row[header] = header
data = [header_row]
data.extend(to_append)
data_writer = csv.DictWriter(output_file, headers)
data_writer.writerows(data)
print str(len(data)) + ' rows written'
ListToCSVWithHeaders(dictList, 'output.csv', WANTED_HEADERS)
Run Code Online (Sandbox Code Playgroud)
这是我在运行时收到的错误.
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 7: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)
您不能将Unicode写入CSV ...但您可以编写恰好是UTF-8(或Latin-1,或几乎任何其他编码*)编码Unicode的字节.文档明确说明了这一点,并建议如何处理它:
注意:此版本的
csv模块不支持Unicode输入.此外,目前有一些关于ASCII NUL字符的问题.因此,所有输入应为UTF-8或可打印ASCII以确保安全; 请参阅示例部分中的示例.这些限制将来会被删除.
该示例部分展示了如何解决这个问题,提供让你读,写的包装unicode对象,编码/解码UTF-8自动为您.如果您正在使用不同的字符集(例如,因为您计划将其传递给需要cp1252编码的CSV的Excel VBscript),请根据需要进行替换'utf-8'.
示例代码做了一些花哨的步法,以确保csv模块本身只需要处理UTF-8,而文件可以在不同的编解码器中.这是处理可能会混淆csv模块的编解码器的好方法.但看起来你只是在寻找Latin-1(或者像cp1252这样的拉丁语1扩展字符集),甚至可能是UTF-8本身.在这种情况下,您可以使用快速而肮脏的解决方案,如下所示:
w.writerows(mydata)
Run Code Online (Sandbox Code Playgroud)
...你可以像这样做一些hacky:
def utf8ify(d):
return dict((k.encode('utf-8'), v.encode('utf-8')) for k, v in d.iteritems())
w.writerows(utf8ify(d))
Run Code Online (Sandbox Code Playgroud)
根据您尝试编写的值,您可能需要更改上述内容.例如,如果原始字典中有Latin-1字符串,则需要以下内容:
k.decode('latin-1').encode('utf-8'), …
Run Code Online (Sandbox Code Playgroud)
如果你不知道你想写的东西......好吧,你不能做快速和肮脏的解决方案.
在您编辑的版本中,您正在以这种方式使用快速和脏的解决方案:
def utf8ify(d):
return dict((str(k).encode('utf-8'), str(v).encode('utf-8')) for k, v in d.iteritems())
Run Code Online (Sandbox Code Playgroud)
...并且您传递的值似乎是unicode字符串的组合,u'\xd3'我认为是UTF-8编码的str字节字符串'Blah \xc3\x93 D\xc3\xa1blah'.那里可能还有一些数字或某些东西,或者你可能只是小心翼翼.
无论如何,那是行不通的; UTF-8编码的字符串将通过未str更改,解码为sys.getdefaultencoding(),并重新编码为UTF-8,而Unicode字符串将使用默认编码进行编码,使用默认编码进行解码,并使用UTF-8重新编码.
如果这是您的实际数据,代码将是这样的:
def utf8ify_s(s):
if isinstance(s, unicode):
return s.encode('utf-8')
else:
return str(s)
Run Code Online (Sandbox Code Playgroud)
这将编码unicode字符串,假设str字符串已经在UTF-8中并传递它们str(这将使它们保持不变),并通过调用将数字等转换为字符串str(对于任何内置类型都可以,并且只要自定义str你写的类型是纯ASCII或UTF-8,对他们来说也没问题.然后,而不是str(…).encode('utf-8')每个,k并v调用此函数:
def utf8ify(d):
return dict(utf8ify_s(k): utf8ify_s(v) for k, v in d.iteritems())
Run Code Online (Sandbox Code Playgroud)
同时,我强烈建议您阅读Unicode HOWTO以及您需要的任何其他内容,以了解这里实际发生的事情,而不是仅仅尝试破解您的代码,直到它看起来有效.
*实际规则是这样的:没有嵌入的NUL字节(因此UTF-16已经出局),没有可以跨越多行的持久状态(因此一些东亚编码已经出局),并且没有"代理"式的部分字符与引号字符的字节匹配的字节数.如果您不确定...使用花式转换器并通过UTF-8.
| 归档时间: |
|
| 查看次数: |
4804 次 |
| 最近记录: |