Python中的JSON和Unicode

6

更新:

我在这里找到了答案: Python UnicodeDecodeError - 我是否误解了编码?

当我读取文件时,我需要将我的输入文件明确地解码为Unicode。因为它包含的字符既不是可接受的ascii字符,也不是Unicode字符。所以当遇到这些字符时,编码过程会失败。

原始问题

所以,我知道这里有些东西我没有理解。

我有一个unicode字符串数组,其中一些包含非Ascii字符。

我想将其编码为json格式。

json.dumps(myList)

它抛出了一个错误。

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

我该怎么做?我尝试将ensure_ascii参数设置为True和False,但都无法解决这个问题。我知道我正在向json.dumps传递unicode字符串。我了解json字符串应该是unicode的。为什么它不能自动解决这个问题呢?

我做错了什么?

更新:Don Question明智地建议我提供堆栈跟踪。这是它:

Traceback (most recent call last):
  File "importFiles.py", line 69, in <module>
    x = u"%s" % conv
  File "importFiles.py", line 62, in __str__
    return self.page.__str__()
  File "importFiles.py", line 37, in __str__
    return json.dumps(self.page(),ensure_ascii=False)
  File "/usr/lib/python2.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 204, in encode
    return ''.join(chunks)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xb4 in position 17: ordinal not in range(128)

请注意,这是Python 2.7版本,并且即使使用ensure_ascii=False选项,错误仍然会发生。

更新2:Andrew Walker在评论中提供的有用链接让我想到,在尝试进行json编码之前,可以将数据强制转换为便捷的字节格式,例如:

data.encode("ascii","ignore")

很遗憾,这仍然出现了相同的错误。

您可能还想查看Ned Batchelder在PyCon 2012上的幻灯片,以更深入地了解Unicode及其与Python 2和3之间的关系。网址为http://nedbatchelder.com/text/unipain.html。 - Andrew Walker
我也在问输出的原因,因为输出的上下文很重要。如果你的输出上下文不是Unicode,就需要转换成它接受的格式。在这种情况下,是ASCII码。当我尝试将Unicode转储到命令行时,就会出现这个问题。 - tkone
tkone 我只是想编写一个简单的命令行脚本,将一些文本文件转换为 Smallest Federated Wiki(https://github.com/WardCunningham/Smallest-Federated-Wiki)的页面,该 Wiki 使用 json 作为其文件格式。最终,json 只需写入文件即可。但是,在尝试写入文件之前,错误在进行 json 编码时就已经出现了。 - interstar
唐问题。好的,我明白了。当我觉得我得到解决方案时,我会“接受”答案。但是,就像我说的,我倾向于提出相当开放的问题,虽然我得到了很多关于我正在尝试解决的问题的好的部分线索,但通常我没有以易于识别的包装形式得到THE答案。对我来说,这听起来像StackOverflow用他们的激励系统搞砸了这里的文化。我开始更喜欢Quora的“感谢”选项,这种礼貌方式不会让人心烦意乱。 - interstar
1
SO更适合解决需要快速解决方案的紧急问题。它比邮件列表更快,比IRC更详细。两全其美。为了使这种“快速”响应起作用,声誉对我来说似乎是一个不错的方法。而且你可以很快得到多个观点,因为所有参与者之间存在一种“竞争”。最终,低AR只会伤害你自己。;-) - Don Question
1个回答

7
尝试添加参数:ensure_ascii = False。特别是在询问与unicode相关的问题时,添加更长(完整)的traceback并声明使用哪个python版本非常有帮助。
引用python文档:版本2.6.7:
如果ensure_ascii为False(默认值:True),则写入fp的一些块可能是Unicode实例,受Python str转换为unicode的规则限制。除非fp.write()明确了解Unicode(如codecs.getwriter()中所示),否则这可能会导致错误。
因此,这个建议可能会引起新问题,但它解决了我遇到的类似问题。我将生成的Unicode字符串传递给StringIO对象,并将其写入文件。
由于python 2.7和sys.getdefaultencoding设置为ascii,json标准库的''.join(chunks)语句通过隐式转换会崩溃,如果chunks没有进行ascii编码!您必须确保任何包含的字符串在之前被转换为与ascii兼容的表示!您可以尝试utf-8编码的字符串,但如果我没记错的话,unicode字符串不起作用。

谢谢Don的问题。我已经将堆栈跟踪添加到问题中。不幸的是,似乎并不是ensure_ascii标志。 - interstar
sys.getdefaultencoding返回ascii?(对于Python 2.7来说是合理的)如果是这样,那么''.join(chunks)将自动尝试将chunks转换为ascii,如果__str__也这样做的话。我猜convimportFiles是你自己的代码? - Don Question
是的。getdefaultencoding() 返回 ascii。那些名称来自我的代码,没错。那么如果 json 库被强制转换为 Ascii 而没有错误处理程序,它该如何应对系统默认设置呢?这是否意味着标准库与 Python 版本之间存在不兼容性? - interstar
不!它就是这样设计的,因为在Python 2.x中,字符串在内部并不以Unicode方式处理!所以这真是个麻烦事……你不能忽视字符串转换,希望它能正常工作。你总是要与转换斗争。你可以查看/usr/lib/python2.7/json/encoder.py源代码,来了解其中的一些情况。你会发现开发者们尽力应对,但对于第一次尝试的人来说,并不是很直观。他们假设你没有提供Unicode,并试图通过友好的方式处理,结果却是灾难!;-) - Don Question
很难确定某人是否理解Unicode及其编码的概念。但是,如果你假设他们不理解,无论他们是否真的理解,他们可能会把这视为一种侮辱!;-) 我试图以图形方式说明这个问题:https://dev59.com/BF7Va4cB1Zd3GeqPKoYr#8592536 ;-) 问题仍然存在,即在Python 2.x中,字符串表示只是一个纯粹的痛苦!;-) - Don Question

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接