将python namedtuples写入csv以防止UnicodeEncodeError

时间:2014-08-12 15:04:09

标签: python csv py2neo

我正在使用py2neo从我的neo4j数据库导出数据。 (在MacOS X上使用Python 2.7)

以下是我一直在使用的代码:

import csv
from py2neo import neo4j, cypher, node, rel
import pprint

ofile  = open('mydata.csv', 'wb')
writer = csv.writer(ofile, delimiter='\t', quotechar='|', quoting = csv.QUOTE_ALL)
graph_db = neo4j.GraphDatabaseService("http://xx.xx.xx.xx:7474/db/data/")
qs = '''MATCH (a:MyLabel) 
WHERE NOT a.shortdesc = ""
RETURN a.name, a.shortdesc, a.longdesc 
ORDER BY a.name'''
query = neo4j.CypherQuery(graph_db, qs)
writer.writerows(query.stream())

在属性a.shortdesc和a.longdesc中显然有一些奇怪的字符,我无法弄清楚如何正确编码它们。我收到了这个错误:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u201c' in position 148: ordinal not in range(128)

我一直在尝试各种不同的事情......我怎样才能使用命名元素并对其进行正确编码,以便将它们写入csv文件?

1 个答案:

答案 0 :(得分:4)

您正在尝试编写包含(以及其他)U+201C LEFT DOUBLE QUOTATION MARK代码点的Unicode数据。

您需要将值编码为UTF-8或找到另一种将Unicode值表示为数据的方法。

编码可以在具有列表推导的生成器表达式中完成,以对每列进行编码:

writer.writerows([unicode(c).encode('utf8') for c in row] for row in query.stream())

unicode()调用确保在尝试编码之前首先将非unicode值转换为unicode字符串。

您还可以尝试“简化”值;您找到的代码点是一个“花哨”的引用,很可能就在那里,因为文字处理器或桌面电子表格应用程序决定用这些引号替换常规引号。如果您的所有数据都只是ASCII文本或数字,您可以尝试用ASCII等价物替换“花哨”的东西。

Unidecode package可以再次用ASCII版本替换此类代码点:

from unidecode import unidecode

writer.writerows([unidecode(unicode(c)) for c in row] for row in query.stream())