Unicode latin1 字符串编码/解码

3

在使用Python(Django)ORM从一个未知/旧的/不一致的Mysql数据库中获取数据并将其存储到Postgres utf-8数据库时,有时会出现编码错误的数据。

目标:grégory

> a
u'gr\xe3\xa9gory'

> print a
grã©gory

我尝试了几种解码/编码技巧,但都没有成功:
 > print a.encode('utf-8').decode('latin1')
 grã©gory

 > print a.encode('utf-8').decode('latin1')
 grã©gory

 > print a.decode('latin-1')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)

即使有一些unicode_escape


你是怎么获取数据的?你那里有一个带有错误字符的Unicode实例;你需要修复首次产生a的解码步骤。你展示的代码发生得太晚了。 - Wooble
即使将数据解释为字节而不是Unicode,其仍然不是有效的UTF8格式。在该编码中不会出现E3 A9。 - Martijn Pieters
1
这个链接可以帮助你在Python 2.x中处理Unicode,它是关于“Unicode三明治”的讲解。 - Amelia
2
这两个字节的正确Unicode代码点是什么?我们可能可以弄清楚出了什么问题,但如果不知道正确的解释是什么,几乎不可能重建。 - Martijn Pieters
最后但并非不重要的是,将编码转换为Latin-1至少可以保留“字节”;Unicode代码点0-255被编码为具有匹配值的字节,因此您可以将这些字节重新解释为不同的编码。 - Martijn Pieters
此外,如果可能的话,您应该提供更多的示例...以查看错误输出中是否存在模式。 - root
3个回答

7

我猜这个字符串在某个时候被错误地转换成了小写字母,将\xc3改为了\xe3。在实际上它是UTF-8编码时,小写转换假定它是Latin1编码。

>>> print 'gr\xc3\xa9gory'.decode('utf8')
grégory

确实,我对获取的字符串执行了lower()操作。在从Mysql读取时,我将尝试在插入级别修复编码/解码问题。谢谢! - coulix
2
@coulix:那是一个至关重要的细节;为什么在修复之前要将小写破损数据? - Martijn Pieters

-1

由于问题出在lower()函数上,我可以通过以下方式修复它:

print a.upper().encode('latin1').lower()

不,'Abcd'.lower().upper()'Abcd'不是同一件事。在首次修复数据之前,OP不应该将其转换为小写。 - Martijn Pieters
并且为了更加明确:有很多部分的UTF-8字节可以被解释为Latin-1 小写字符,而将它们转换成大写会破坏这些字节。调用.upper()只会引入更多错误。 - Martijn Pieters

-6

试试这个:

print a.decode('latin1')

这会有什么帮助? - root
a 是一个 unicode 对象;调用 .decode() 意味着首先有一个 .encode()。在这种情况下,数据应该编码成什么?Python 将默认使用 ASCII 编码,而 E3 和 A9 字节将失败。 - Martijn Pieters

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