Python:' ascii'编解码器不能解码字节

时间:2017-10-04 18:18:02

标签: python

当前代码:

 file.write("\"" + key + "\": " + "\"" + french[key].encode('utf8') + "\"" + ',' + '\n')

其中字典中的法语键值如下所示:

"YOU_HAVE_COMPLETED_ENROLLMENT": "Vous avez termin\u00e9 l'inscription !"

出现此错误:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 19: ordinal not in range(128)

在这里尝试了所有解决方案,但似乎都没有。

2 个答案:

答案 0 :(得分:1)

解决方案:在编码之前连接unicode字符串,然后在写入文件之前对完整字符串进行编码。 codecs库为您简化了这一过程。

import codecs

file = codecs.open(os.path.join(fr_directory, 'strings.json'), 'w+', encoding='utf8')
file.write("\"" + key + "\": " + "\"" + french[key] + "\"" + ',' + '\n')

我已使用codecs.open而不是open打开文件,指定在编写unicode字符串时文件应自动处理UTF-8编码。我还删除了您使用的显式编码调用。

进一步说明:

字典的键和值几乎肯定是Unicode字符串。在将“Unicode字符串”写入文件之前,需要对其进行编码。除非另有说明,否则Python 2中的大多数操作都采用ASCII编码,open返回的文件对象就在其中。这就是为什么,如果你尝试将Unicode字符串写入文件,你会看到一个例外:

>>> with open('/tmp/test.txt', 'w') as f:
...    f.write(u"Vous avez termin\xe9 l'inscription !")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 16: ordinal not in range(128)

您可以通过直接对字符串进行编码来修复此错误,因此可以正常工作:

>>> with open('/tmp/test.txt', 'w') as f:
...    f.write(u"Vous avez termin\xe9 l'inscription !".encode('utf-8'))

但是,仅此一项并不能解决您的问题,因为您正在尝试构建更复杂的字符串。将Unicode字符串连接到UTF-8编码的“原始”字符串时,即使不写入文件,也会出现异常:

>>> u"YOU_HAVE_COMPLETED_ENROLLMENT: " + u"Vous avez termin\xe9 l'inscription !".encode('utf-8')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)

您可以通过 not 编码来解决此问题:

>>> u"YOU_HAVE_COMPLETED_ENROLLMENT: " + u"Vous avez termin\xe9 l'inscription !"
u"YOU_HAVE_COMPLETED_ENROLLMENT: Vous avez termin\xe9 l'inscription !"

但是当你想把它写到文件中时,你必须再次对整个事物进行编码:

>>> with open('/tmp/test.txt', 'w') as f:
...    line = u"YOU_HAVE_COMPLETED_ENROLLMENT: " + u"Vous avez termin\xe9 l'inscription !"
...    f.write(line.encode('utf-8'))

但为方便起见,codecs模块为您提供了不必每次都重新编码的工具:

>>> import codecs
>>> with codecs.open('/tmp/test.txt', 'w', encoding='utf8') as f:
...    f.write(u"YOU_HAVE_COMPLETED_ENROLLMENT: " + u"Vous avez termin\xe9 l'inscription !")

答案 1 :(得分:1)

你可以使用这个函数unicode字符串

def _parse_value(value):
    if type(value) == str:
        value = value.decode("utf-8", "ignore").strip()
    return value