【问题标题】:Python decoding issue with Chinese characters中文字符的Python解码问题
【发布时间】:2016-10-31 04:53:45
【问题描述】:

我正在使用 Python 3.5,我正在尝试获取可能包含或不包含特殊中文字符的字节文本块并将其输出到文件中。它适用于不包含中文字符的条目,但在包含中文字符时会中断。汉字永远是一个人的名字,而且总是除了他们名字的英文拼写。文本是 JSON 格式的,需要先解码才能加载。解码似乎很顺利,没有给我任何错误。当我尝试将解码后的文本写入文件时,它会给我以下错误消息:

UnicodeEncodeError:“charmap”编解码器无法对位置 14-18 中的字符进行编码:字符映射到未定义

这是我在对其进行任何操作之前获得的原始数据的示例:

 b'  "isBulkRecipient": "false",\r\n      "name": "Name in, English \xef'
 b'\xab\x62\xb6\xe2\x15\x8a\x8b\x8a\xee\xab\x89\xcf\xbc\x8a",\r\n

这是我正在使用的代码:

recipientData = json.loads(recipientContent.decode('utf-8', 'ignore'))
recipientName = recipientData['signers'][0]['name']
pprint(recipientName)
with open('envelope recipient list.csv', 'a', newline='') as fp:
    a = csv.writer(fp, delimiter=',')
    csvData = [[recipientName]]
    a.writerows(csvData)

recipientContent 是从 API 调用中获得的。我不需要在输出文件中有中文字符。任何建议将不胜感激!

更新:

我一直在为每个中断的条目做一些手动解决方法,并出现其他不包含中文特殊字符但来自其他语言的条目,并且也破坏了程序。特殊字符仅在名称字段中。因此,名称可能类似于“Ałex”,其中混合了普通字符和特殊字符。在我解码包含此信息的字符串之前,我可以将其打印到屏幕上,它看起来像这样:b'name": "A\xc5ex",\r\n

但在我将其解码为 utf-8 后,如果我尝试输出它会给我一个错误。错误信息是:UnicodeEncodeError: 'charmap' codec can't encode character 'u0142' in position 2- character maps to -undefined-

我查了一下 \u0142 是什么,它是 ł 特殊字符。

【问题讨论】:

  • 示例字符串似乎不是 UTF-8(也不是任何常见的中文多字节编码)。你确定是 UTF-8 编码(甚至是中文)?
  • 你必须检查Content-Type。如果是application/json; charset=utf-16,请使用utf-16application/json 的默认值为 utf-8
  • 我不能 100% 确定它的 utf-8,因为我从中获取数据的 Web 服务没有很好地记录它,但我尝试了几种不同的编码类型,包括 utf- 16.我确定它包含汉字。
  • 每个http响应都有Content-Type。你应该在解码之前检查它。
  • 您在 Windows 上吗?你能发布完整的回溯吗?

标签: python python-3.x encoding python-unicode


【解决方案1】:

将此行添加到您的代码中:

from __future__ import unicode_literals

【讨论】:

  • 为什么会有帮助?
【解决方案2】:

您在写入文件时遇到的错误。

在 Python 3.x 中,当您在文本模式(默认)下 open() 而不指定 encoding= 时,Python 将使用最适合您的语言环境或语言设置的编码。

如果您使用的是 Windows,这将使用 charmap 编解码器映射到您的语言编码。

虽然您可以直接将字节写入文件,但首先将其解码是正确的做法。正如其他人所说,您应该真正使用 Web 服务器指定的编码进行解码。您还可以使用 Python Requests 模块,它会为您执行此操作。 (您的示例未解码为 UTF-8,因此我认为您的示例不正确)

要解决您的直接错误,只需将encoding 传递给open(),它支持您在数据中的字符。 UTF-8 编码中的 Unicode 是显而易见的选择。因此,您应该将代码更改为:

with open('envelope recipient list.csv', 'a', encoding='utf-8', newline='') as fp:

【讨论】:

    【解决方案3】:

    警告:前方有霰弹枪解决方案

    假设您只想删除所有文件中的所有外来字符(即它们对于您将来处理所有其他字段并不重要),您可以简单地忽略所有非 ascii 字符

    recipientData = json.loads(recipientContent.decode('utf-8', 'ignore'))
    

    通过

    recipientData = json.loads(recipientContent.decode('ascii', 'ignore'))
    

    这样,您在以后处理之前删除所有非 ascii 字符。

    我将其称为霰弹枪解决方案,因为它在某些情况下可能无法正常工作:

    1. 显然,如果需要保留非 ascii 字符以供将来使用
    2. 如果 b'\'b" 字符出现在例如 utf-16 字符的一部分中。

    【讨论】:

      猜你喜欢
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-05
      • 2011-07-14
      • 1970-01-01
      • 2013-04-21
      相关资源
      最近更新 更多