gpt4 book ai didi

python - python 2.x 中 json.dump 后 json.loads 上的 UnicodeDecodeError 与 Ensure_ascii=False

转载 作者:太空宇宙 更新时间:2023-11-03 16:50:32 24 4
gpt4 key购买 nike

我使用 json.dump 转储 dict 对象。为了避免 UnicodeDecodeError,我按照 this advice 设置了 ensure_ascii=False .

with open(my_file_path, "w") as f:
f.write(json.dumps(my_dict, ensure_ascii=False))

转储文件已成功创建,但加载转储文件时出现 UnicodeDecodeError:

with open(my_file_path, "r") as f:
return json.loads(f.read())

如何避免加载转储文件时出现UnicodeDecodeError

错误消息和堆栈跟踪

错误消息是UnicodeDecodeError:'utf8'编解码器无法解码位置0中的字节0x93:无效的起始字节并且堆栈跟踪是:

/Users/name/.pyenv/versions/anaconda-2.0.1/python.app/Contents/lib/python2.7/json/__init__.pyc in loads(s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
336 if (cls is None and encoding is None and object_hook is None and
337 parse_int is None and parse_float is None and
--> 338 parse_constant is None and object_pairs_hook is None and not kw):
339 return _default_decoder.decode(s)
340 if cls is None:

/Users/name/.pyenv/versions/anaconda-2.0.1/python.app/Contents/lib/python2.7/json/decoder.pyc in decode(self, s, _w)
364 obj, end = self.raw_decode(s, idx=_w(s, 0).end())
365 end = _w(s, end).end()
--> 366 if end != len(s):
367 raise ValueError(errmsg("Extra data", s, end, len(s)))
368 return obj

/Users/name/.pyenv/versions/anaconda-2.0.1/python.app/Contents/lib/python2.7/json/decoder.pyc in raw_decode(self, s, idx)
380 obj, end = self.scan_once(s, idx)
381 except StopIteration:
--> 382 raise ValueError("No JSON object could be decoded")
383 return obj, end

UnicodeDecodeError: 'utf8' codec can't decode byte 0x93 in position 0: invalid start byte

最佳答案

在Python2中,您可以在调用json.loads之前使用ensure_ascii=False并解码结果:

import json

my_dict = {b'\x93': [b'foo', b'\x93', {b'\x93': b'\x93'}]}

dumped = json.dumps(my_dict, ensure_ascii=False)
print(repr(dumped))
# '{"\\u201c": ["foo", "\\u201c", {"\\u201c": "\\u201c"}]}'
result = json.loads(dumped.decode('cp1252'))
print(result)
# {u'\u201c': [u'foo', u'\u201c', {u'\u201c': u'\u201c'}]}

但是请注意,json.loads 返回的结果包含unicode,而不是str。因此结果my_dict并不完全相同。

请注意json.loads always decodes strings to unicode ,因此,如果您有兴趣使用 json.dumpsjson.loads 忠实地恢复字典,那么您需要从仅包含 unicode< 的字典开始,没有 strs。

此外,在 Python3 中 json.dumps 要求所有字典的键都是 unicode 字符串。所以上面的解决方案在Python3中不起作用。

<小时/>

在 Python2 和 Python3 中都可以使用的替代方法是确保您传递 json.loads 一个字典,其键和值为 unicode (或不包含strs)。例如,如果您使用 convert (如下)递归地更改键和值在传递给 json.loads 之前先转换为 unicode:

import json

def convert(obj, enc):
if isinstance(obj, str):
return obj.decode(enc)
if isinstance(obj, (list, tuple)):
return [convert(item, enc) for item in obj]
if isinstance(obj, dict):
return {convert(key, enc) : convert(val, enc)
for key, val in obj.items()}
else: return obj

my_dict = {'\x93': ['foo', '\x93', {'\x93': '\x93'}]}
my_dict = convert(my_dict, 'cp1252')

dumped = json.dumps(my_dict)
print(repr(dumped))
# '{"\\u201c": ["foo", "\\u201c", {"\\u201c": "\\u201c"}]}'
result = json.loads(dumped)
print(result)
# {u'\u201c': [u'foo', u'\u201c', {u'\u201c': u'\u201c'}]}
assert result == my_dict

convert 将解码 my_dict 内的列表、元组和字典中找到的所有 str

上面,我使用 'cp1252' 作为编码,因为(如 Fumu pointed out )用 cp1252 解码的 '\x93'左双引号:

In [18]: import unicodedata as UDAT

In [19]: UDAT.name('\x93'.decode('cp1252'))
Out[19]: 'LEFT DOUBLE QUOTATION MARK'

如果您知道 my_dict 中的 str 已使用其他编码进行编码,您当然应该使用该编码来调用 convert

<小时/>

更好的是,不要使用 convert,而是在构建时注意确保所有 str 都解码为 unicode my_dict

关于python - python 2.x 中 json.dump 后 json.loads 上的 UnicodeDecodeError 与 Ensure_ascii=False,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35880789/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com