2

我正在尝试将包含 utf-8 字符串的字典写入 CSV。我正在按照这里的说明进行操作。然而,尽管对这些 utf-8 字符串进行了精心编码和解码,但我得到了一个涉及“ascii”集的 UnicodeEncodeErrors。

我有一个字典列表,其中包含字符串和整数作为与维基百科文章更改相关的值。下面的列表对应于这种变化,例如:

edgelist = [{'articleName': 'Barack Obama', 'editorName': 'Schonbrunn', 'revID': '121844749', 'bytesAdded': '183'}, 
{'articleName': 'Barack Obama', 'editorName': 'Eep\xc2\xb2', 'revID': '121862749', 'bytesAdded': '107'}]

问题是list[1]['editorName']。它有类型'str'并且el[1]['editorName'].decode('utf-8')u'Eep\xb2'

我正在尝试的代码是:

_ENCODING = 'utf-8'
def dictToCSV(edgelist,output_file):
    with codecs.open(output_file,'wb',encoding=_ENCODING) as f:
        w = csv.DictWriter(f,sorted(edgelist[0].keys()))
        w.writeheader()
        for d in edgelist:
            for k,v in d.items():
                if type(v) == int:
                    d[k]=str(v).encode(_ENCODING)
            w.writerow({k:v.decode(_ENCODING) for k,v in d.items()})

这将返回:

dictToCSV(edgelist,'test2.csv')
File "csv_to_charts.py", line 129, in dictToCSV
w.writerow({k:v.decode(_ENCODING,'ignore') for k,v in d.items()})
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/csv.py", line 148, in writerow
return self.writer.writerow(self._dict_to_list(rowdict))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xb2' in position 3: ordinal not in range(128)

其他排列,例如将 decode 交换为 encode 或最后有问题的行中没有任何内容也会返回错误:

  1. w.writerow({k:v.encode(_ENCODING) for k,v in d.items()})返回'UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 56: ordinal not in range(128)
  2. w.writerow({k:v for k,v in d.items()})返回UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 56: ordinal not in range(128)
  3. 之后,我更改with codecs.open(output_file,'wb',encoding=_ENCODING) as f:with open(output_file,'wb') as f:并仍然收到相同的错误。

排除列表元素或包含此有问题的字符串的键,否则脚本可以正常工作。

4

3 回答 3

3

我刚刚按如下方式编辑了您的代码,并且 csv 已成功编写。

from django.utils.encoding import smart_str
import csv

def dictToCSV(edgelist, output_file):
    f = open(output_file, 'wb')
    w = csv.DictWriter(f, fieldnames=sorted(edgelist[0].keys()))
    w.writeheader()
    for d in edgelist:
        w.writerow(dict(k=smart_str(v)) for k, v in d.items())
    f.close()

复制 Django 代码并根据需要对其进行自定义。

于 2012-08-03T18:05:44.837 回答
0

ASCII 编码的严格解释只允许序数 0-127。根据定义,超出该范围的任何值都不是 ASCII。由于 \xc2 和 \xb2 的序数均高于 127,因此它们不能被解释为 ASCII。

我不是 Python 用户CSV 的 RFC提到 ASCII 作为一种常见用法,但为 MIME 类型定义了一个可选的 'charset' 参数;我想知道您使用的作家是否也可能有“编码”设置?

于 2012-08-03T17:56:30.970 回答
0

您的字符串已经采用 UTF-8 格式,而 DictWriter 不适用于codecs.open. 按照那个例子:

# coding: utf-8
import csv

edgelist = [
    {'articleName': 'Barack Obama', 'editorName': 'Schonbrunn', 'revID': '121844749', 'bytesAdded': '183'},
    {'articleName': 'Barack Obama', 'editorName': 'Eep\xc2\xb2', 'revID': '121862749', 'bytesAdded': '107'}]

with open('out.csv','wb') as f:
    f.write(u'\ufeff'.encode('utf8')) # BOM (optional...Excel needs it to open UTF-8 file properly)
    w = csv.DictWriter(f,sorted(edgelist[0].keys()))
    w.writeheader()
    for d in edgelist:
        w.writerow(d)

输出:

articleName,bytesAdded,editorName,revID
Barack Obama,183,Schonbrunn,121844749
Barack Obama,107,Eep²,121862749

注意,您可以'editorName': 'Eep²'直接使用而不是'editorName': 'Eep\xc2\xb2'. # coding: utf-8如果您将源文件保存为 UTF-8,则字节字符串将按 UTF-8 编码。

于 2012-08-04T00:43:46.823 回答