Python字符串编码问题

时间:2012-01-30 07:20:31

标签: python django unicode encoding

我使用亚马逊MWS API获取商店的销售报告,然后将该报告保存在数据库的表格中。不幸的是,当我尝试将信息编码为Unicode时,我收到了编码错误。在查看报告后(正如亚马逊发送的那样),我看到了这个字符串,这是买家的位置:

  

'S oPaulo'

所以我试着像这样编码:

encodeme = 'S�o Paulo'
encodeme.encode('utf-8)

但出现以下错误

  

UnicodeDecodeError:'ascii'编解码器无法解码位置1的字节0xef:序号不在范围内(128)

我尝试对其进行编码的全部原因是因为一旦Django看到字符,它就会抛出警告并切断字符串,这意味着该位置将保存为S

  

圣保罗

感谢任何帮助。

3 个答案:

答案 0 :(得分:4)

我认为您必须使用正确的编码对其进行解码,而不是将其编码为utf-8。试试

s = s.decode('utf-8')

但是,您需要知道要使用的编码。输入可以带有utf-8的其他编码。

您收到的错误UnicodeDecodeError表示您的对象不是unicode,而是字节字符串。执行bytestring.encode时,首先将字符串解码为具有默认编码(ascii)的unicode对象,然后使用utf-8进行编码。

我将尝试解释python中unicode stringutf-8 bytestring的区别。

unicode是一个python的数据类型,表示一个unicode字符串。对程序中的大多数字符串操作使用unicode。 Python可能在其内部使用utf-8虽然它也可以是utf-16,但这对你来说无关紧要。

bytestring是二进制安全字符串。它可以是任何编码。当您接收数据时,例如打开文件,您会得到一个字节串,在大多数情况下,您需要将其解码为unicode。写入文件时,必须将unicode对象编码为字节串。有时解码/编码是由框架或库完成的。但并不总是框架可以做到这一点,因为并不总是框架可以知道使用哪种编码。

utf-8是一种编码,它可以正确地将任何unicode字符串表示为bytestring。但是,您无法使用utf-8将任何类型的字节串解码为unicode。您需要知道在字节串中使用什么编码来解码它。

答案 1 :(得分:3)

看起来你遇到了某种编码问题。

首先,您应该非常确定亚马逊在他们发送给您的报告正文中使用的编码方式。是UTF-8吗?是ISO 8859-1吗?还有别的吗?

不幸的是,Amazon MWS Reports API documentation,特别是他们的API Reference,对他们使用的编码不是很了解。他们只编码我看到他们提到的是UTF-8,所以这应该是你的第一个猜测。 GetReport API文档(p.36-37)将响应元素Report描述为类型xs:string,但我没有看到它们定义该数据类型的位置。也许他们的意思是XML Schema's string datatype

因此,我建议您将从Amazon收到的字节序列作为报表正文保存在文件中,并保持零转换。请注意,调用AWS的代码可能会无意中修改报表正文字符串。使用二进制编辑器检查该文件中的非ASCII字节。 “São”的“São”是否存储为S\xC3\xA3o,表示UTF-8编码?或者它是否存储为S\xE3o,表示ISO 8859-1编码?

我猜你是以平面文件的形式收到报告的。 Amazon AWS文档说您可以请求将报告作为XML提供给您。这样做的好处是可以使用显式编码声明给你回复。

了解报告正文的编码后,您现在需要正确处理它。您暗示您正在使用Django框架和Python语言代码从Amazon AWS接收报告。

要明确的一件事(正如Skirmantas所解释的那样):

  • Unicode字符串包含字符。字节字符串保存字节(八位字节)。
  • 编码将Unicode字符串转换为字节字符串。
  • 解码将字节字符串转换为Unicode字符串。

您从Amazon AWS获得的字符串是 byte 字符串。您需要解码才能获得Unicode字符串。但是您的代码片段encodeme = 'São Paulo'为您提供了一个字节字符串。 encodeme.encode('utf-8)对字节字符串执行encode(),这不是您想要的。 ('utf-8上缺少的结束语无济于事。)

试试这个示例代码:

>>> reportbody = 'S\xc3\xa3o Paulo'   # UTF-8 encoded byte string
>>> reportbody.decode('utf-8')        # returns a Unicode string, u'...'
u'S\xe3o Paulo'

您可能会发现一些背景阅读很有帮助。我同意Hoxieboy你应该花时间阅读Python's Unicode HOWTO。另请查看What do I need to know about Unicode?的热门答案。

答案 2 :(得分:1)

Official Python unicode documentation

您可以尝试使用该网页,如果您还没有,看看您是否能找到您想要的答案;)