Python json忽略nonascii字符UnicodeDecodeError:“ascii”编解码器无法解码

2024-09-28 21:34:33 发布

您现在位置:Python中文网/ 问答频道 /正文

Python 2.7.3

我已经阅读了关于json/dumps UnicodeDecodeError的所有相关线程,其中大多数希望我理解我需要什么编码。在我的例子中,我创建了一个json,其中包含来自不同服务(一些p4命令行)的各种键值,可能是不同的编码。我有一张类似这样的地图

map = {"system1": some_data_from_system1, "system2", some_data_from_system2}
json.dumps(map)

“无法在该位置中使用ascii DECODER(0x73DEOR not CODER7)”

我希望有ASCII字符转储到一个文件偶尔p4签入/jira可能有非ASCII字符,这是完全可以忽略这一点。我尝试过“确保ascii=False”,但它不能解决问题。我真正想要的是编码器简单地忽略任何非ascii字符。我认为这是合理的,但找不到任何出路。在

建议?在


Tags: fromjsonmap编码dataasciisome字符
3条回答

我使用了How to get string objects instead of Unicode ones from JSON in Python?和上面的答案的组合来完成这段日志记录。在

如上所述,some_data_from_system{1|2}不是字符串。问题是关于一个通用的错误日志系统。当出现问题时,您希望从多个子系统中转储尽可能多的信息,以供人员检查。当这些子系统之间不知道什么是编码错误的时候。为此,我从另一个线程中窃取了以下方法,但其本质基本上是带有“ignore”的decode方法

请注意:这不是一种性能很好的方法(大多数盲递归通常不是这样)。因此,这不适合典型的生产应用程序;根据数据,它可能会运行到一个无限循环中。但是,假设您理解免责声明,对于错误日志系统来说,这是好的。在

def convert_encoding(data, encoding = 'ascii'):
    if isinstance(data, dict):
        return dict((convert_encoding(key), convert_encoding(value)) \
             for key, value in data.iteritems())
    elif isinstance(data, list):
        return [convert_encoding(element) for element in data]
    elif isinstance(data, unicode):
        return data.encode(encoding, 'ignore')
    else:
        return data

map = {"system1": some_data_from_system1, "system2", some_data_from_system2}
json.dumps(convert_encoding(map), ensure_ascii = False)

一旦完成,这个通用方法就可以用来转储数据。在

如果json格式的字符串包含非ASCII字符,并且需要相应地使用python的dump方法:

myString = "{key: 'Brazilian Portuguese has many differenct characters like  maçã (apple) or Bíblia (Blible)' }" # or a map
myJSON = json.dumps(myString, encoding="latin-1") #use utf8 if appropriate
myJSON = json.loads(myJSON)

当传入时,json.dumps()json.dump()函数将尝试将字节字符串解码为Unicode值,默认情况下使用UTF-8:

>>> map = {"system1": '\x92'}
>>> json.dumps(map)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/__init__.py", line 243, in dumps
    return _default_encoder.encode(obj)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x92 in position 0: invalid start byte
>>> map = {"system1": u'\x92'.encode('utf8')}
>>> json.dumps(map)
'{"system1": "\\u0092"}'

您可以设置encoding关键字参数,以便对字节字符串(str)字符使用不同的编码。在

这些函数之所以这样做,是因为JSON是一个对所有字符串使用Unicode的标准。如果您向它提供编码为UTF-8的而不是的数据,则会失败,如上所示。在

在python2上,输出也是一个字节字符串,编码为UTF-8。它可以安全地写入文件。将ensure_ascii参数设置为False会改变这一点,而您将得到Unicode,这显然不是您想要的。在

因此,您需要确保将放入json.dumps()函数的编码始终相同,已经被解码为unicode对象。如果您不关心偶尔丢失的代码点,您可以通过将错误处理程序设置为replaceignore来强制解码:

^{pr2}$

这将强制解码字符串,用替换字符替换未识别为ASCII码位的任何字节:

>>> '\x92'.decode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0x92 in position 0: ordinal not in range(128)
>>> '\x92'.decode('ascii', errors='replace')
u'\ufffd'

这里插入一个U+FFFD REPLACEMENT CHARACTER代码点来表示未知的代码点。也可以使用errors='ignore'完全忽略这些字节。在

相关问题 更多 >