Python Unicode CSV导出(使用Django)

时间:2010-10-14 01:08:18

标签: python unicode utf-8 csv ascii

我正在使用Django应用将字符串导出为CSV文件。该字符串是通过前端表单提交的消息。但是,当输入中提供了unicode单引号时,我一直收到此错误。

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

我一直在尝试使用下面的代码将unicode转换为ascii,但仍会遇到类似的错误。

UnicodeEncodeError: 'ascii' codec can't encode characters in 
position 0-9: ordinal not in range(128)

我已经筛选了几十个网站并学到了很多关于unicode的知识,但是,我仍然无法将这个unicode转换为ascii。我不在乎算法是否删除了unicode字符。注释的行表示我尝试过的各种选项,但错误仍然存​​在。

import csv
import unicodedata

...

#message = unicode( unicodedata.normalize(
#                            'NFKD',contact.message).encode('ascii','ignore'))
#dmessage = (contact.message).encode('utf-8','ignore')
#dmessage = contact.message.decode("utf-8")
#dmessage = "%s" % dmessage
dmessage = contact.message

csv_writer.writerow([
        dmessage,
])

有没有人有任何关于删除unicode字符的建议我可以将它们导出为CSV?这个看似简单的问题让我头晕目眩。任何帮助深表感谢。 谢谢, 乔

3 个答案:

答案 0 :(得分:7)

您不能将Unicode字符u'\u2019'(U + 2019右单引号)编码为ASCII,因为ASCII中没有该字符。 ASCII只是基本的拉丁字母,数字和标点符号;你没有像这个角色那样得到任何重音字母或“智能引号”。

因此您必须选择其他编码。现在通常明智的做法是导出到UTF-8,它可以容纳任何Unicode字符。不幸的是,如果您的目标用户正在使用Office(他们可能是),他们将无法以CSV格式读取UTF-8编码的字符。相反,Excel将使用该计算机的系统默认代码页读取文件(也误称为'ANSI'代码页),最后使用’而不是的mojibake。

因此,如果您希望字符正确显示,则意味着您必须猜测用户的系统默认代码页。对于西方用户来说,这将是代码页1252.使用非西方Windows安装的用户会看到错误的字符,但是你无法做到这一点(除了组织写给Microsoft的写信活动,只是为了放弃愚蠢的废话与ANSI已经和其他人一样使用UTF-8。

代码页1252可以包含U + 2019(),但显然还有更多不能代表的字符。为避免获得UnicodeEncodeError这些字符,您可以使用ignore参数(或replace将其替换为问号)。

dmessage= contact.message.encode('cp1252', 'ignore')

或者,放弃并删除所有非ASCII字符,这样无论语言环境如何,每个人都会获得同样糟糕的体验:

dmessage= contact.message.encode('ascii', 'ignore')

答案 1 :(得分:2)

编码是一种痛苦,但如果您在django工作,您是否尝试过smart_unicode(str) django.utils.encoding?我发现通常会有这个伎俩。

我发现的唯一另一个选择是使用内置的python encode()decode()作为字符串,但你必须为这些指定编码,老实说,这很痛苦。< / p>

答案 2 :(得分:1)

[警告:我不是djangoist; django可能有更好的解决方案]。

一般非django特定答案:

如果您有少量已知的非ASCII字符并且有相应的用户可接受的ASCII等效字符,则可以设置转换表并使用unicode.translate方法:

smashcii = {
    0x2019 : u"'",
    # etc
    #

smashed = input_string.translate(smashcii)