3

我创建了一个包含字典的文件,其中包含用西班牙语编写的数据(即Damián等):

fileNameX.write(json.dumps(dictionaryX, indent=4))

数据来自一些fql获取操作,即:

select name from user where uid in XXX

例如,当我打开文件时,我发现“Damián”看起来像“Dami\u00e1n”。我尝试了一些选择:

  1. 确保ASCII=假:

    fileNameX.write(json.dumps(dictionaryX, indent=4, ensure_ascii=False))
    

    但是我收到一个错误(UnicodeEncodeError: 'ascii' codec can´t encode character u'\xe1' in position XXX: ordinal not in range(128))。

  2. 编码(编码='latin-1):

    dictionaryX.append({
        'name': unicodeVar.encode(encoding='latin-1'),
         ...
         })
    

    但我得到另一个错误(UnicodeDecodeError: 'utf8' codec can't decode byte 0xe1 in position XXX: invalid continuation byte

总而言之,我尝试了几种可能性,但没有一个线索。我迷路了。拜托,我需要帮助。谢谢!

4

3 回答 3

2

用于以特定编码codecs.open()打开,例如,而不是使用.fileNameX encoding='utf-8'open()

另外,json.dump().

于 2012-09-16T21:30:38.320 回答
2

你有很多选择,并且偶然发现了一些相当复杂的东西,它取决于你的 Python 版本,你必须完全理解才能编写正确的代码。一般来说,3.x 中采用的方法更严格,也更难使用,但您犯错误或陷入复杂情况的可能性要小得多。(根据您报告的确切症状,您似乎使用的是 2.x。)

json.dumps在 2.x 和 3.x 中具有不同的行为。在 2.x 中,它产生一个str,它是一个字节串(未知编码)。在 3.x 中,它仍然产生一个str,但现在str在 3.x 中是一个正确的 Unicode 字符串。

JSON 本质上是一种支持 Unicode 的格式,但它要求文件采用 UTF-8 编码。但是,请理解 JSON支持\u字符串中的样式转义。当您读入此数据时,您将获得正确的编码字符串。读取代码从 JSON 中读取字符串时会生成 unicode 对象(无论您使用 2.x 还是 3.x)。

当我打开文件时,我发现例如“Damián”看起来像“Dami\u00e1n”

á不能用 ASCII 表示。它被默认编码\u00e1,以避免您遇到的其他问题。即使在 3.x 中也会发生这种情况。

ensure_ascii=False

这将禁用以前的编码。在 2.x 中,这意味着您将获得一个unicode对象 - 一个真正的 Unicode 对象,保留原始á字符。在 3.x 中,这意味着字符没有被显式翻译。但无论哪种方式,都ensure_ascii=False意味着json.dumps 会给你一个 Unicode string

Unicode 字符串必须经过编码才能写入文件。没有“unicode 数据”之类的东西;Unicode 是一种抽象。'ascii'在 2.x 中,当您将 Unicode 对象提供给file.write;时,此编码是隐式的。它期待一个str. 为了解决这个问题,您可以使用该模块,或者像编写之前codecs一样显式编码。'utf-8'在 3.x 中,编码是在文件encoding时使用关键字参数设置open的(默认值可能又不是您想要的)。

编码(编码='latin-1')

在这里,您在生成字典之前进行编码,以便str您的数据中有一个对象。现在出现了一个问题,因为当您的数据中有str对象时,JSON 编码器默认假定它们以 UTF-8 编码表示 Unicode 字符串。这可以在 2.x 中使用encoding关键字参数来更改json.dumps。(在 3.x 中,编码器将简单地拒绝序列化bytes对象,即非 Unicode 字符串!)


但是,如果您的目标只是将数据直接放入文件中,那么json.dumps您的工具就不对了。你有没有想过s这个名字是干什么用的?它代表“字符串”;这是特例。普通的情况,其实就是直接写入文件!(而不是给你一个字符串并期望你自己写。)这就是json.dump(no 's') 所做的。同样,JSON 标准需要 UTF-8 编码,并且 2.x 有一个encoding默认为 UTF-8 的关键字参数(您应该不理会它)。

于 2012-09-16T22:17:52.250 回答
0

由于字符串\u内部有一个,这意味着它是一个 Unicode 字符串。字符串实际上是正确的!您的问题在于显示字符串。如果你print是字符串,Python 的输出编码应该以适合你​​环境的编码打印它。

例如,这是我在 Windows 上的 IDLE 中得到的:

>>> print u'Dami\u00e1n'
Damián
于 2012-09-16T22:24:32.957 回答