Python了解unicode转换

时间:2016-12-12 13:14:20

标签: python unicode python-unicode

我有一个文本数据集,它有一些编码问题。 作者指示:

for line in fpointer:
    line.encode('latin-1').decode('utf-8')

解决问题。

我想知道为什么需要它,我在修复之前打开了文件并看到了这一行:

103 But in Imax 3-D , the clichés disappear into the vertiginous perspectives opened up by the photography .

转换后,它变为:

103 But in Imax 3-D , the clichés disappear into the vertiginous perspectives opened up by the photography .

这很有道理。

但是我无法理解可能导致原始问题的原因以及该修复是如何工作的?

我引用了unicode python链接:https://docs.python.org/3/howto/unicode.html

我还检查了字符及其值:

é的utf-8编码是c3a9,Ã的iso-8859-1编码是c3,而©是a9。

这有点意义,但我无法建立连接。

该行如何存储在原始文件中以及代码片段如何修复它?

3 个答案:

答案 0 :(得分:3)

所以 - 发生的事情是你曾经被“双重编码”为utf-8的文本。

因此,在生成您拥有的数据的过程中的某个时刻,已经具有“é”的内部表示“\ xc3 \ xa9”的文本被解释为处于latin-1中,并且重新 - 从“latin1”(其中“\ xc3 \ xa9”代表“Ô)转换为utf-8,以便将ach字符扩展为两个字节,变为:“\ xc3 \ x83 “”\ xc2 \ xa9“(utf-8代表”Ó)。正如@Novoselov在另一个答案中所说的那样,这种损坏很可能是因为你打开文件读取文本,而没有在Windows上指定编码:Python会认为文件是“latin-1”,默认的Windows编码,因此读取其中的每个字节,它是一个-8字符序列的一部分,作为单个latin-1字符。

修复程序做了什么:您的系统设置已经配置为以utf-8读取文本 - 所以当您在for循环中获得行时,您可以正确解释UTF-的Python-3字符串(Python-2 unicode)文本文件中有8个字符。所以4字节序列变成了2个文本字符。现在,“latin1”编码的一个特征是它是“透明的”:它相当于在文本字节中根本不执行变换。换句话说,由Python的Unicode内部表示中的单个字节中的值表示的每个字符在编码的字节串中变为单个字节。 (并且其值不适合字节的每个字符都不能编码为Latin-1,从而产生Unicode-Encode错误)。

因此,在“透明”编码步骤之后,您有表示文本的字节 - 这次只有utf-8编码的“一次通过”。将这些字节解码为“utf-8”会为您生成正确的文件文本。

再次:

这是原文: “陈词滥调”。编码为UTF-8就像这样: b'clich \ XC3版权所有\ xA9' 但创建文件的原始过程认为此序列为latin-1,因此重新转换为> utf-8为0x80个字符: b'clich \ XC3 \ X83 \ XC2版权所有\ xA9' 。 这就是打印成“cliché”

的内容

在阅读时,Python3读取: 来自磁盘的b'clich \ xc3 \ x83 \ xc2 \ xa9',并返回“cliché”作为(unicode)文本。 你将其编码为字节,并通过调用“encode('latin-1')得到b'clich \ xc3 \ xa9'。最后你从”utf-8“”解码“得到文本”cliché“。

Python3不容易让人破坏这样的文本。要从文本转到不正确的版本,还必须使用“透明”编码“latin-1” - 这是一个例子:

In [10]: a = "cliché"

In [11]: b = a.encode("utf-8")

In [12]: b
Out[12]: b'clich\xc3\xa9'

In [13]: c = b.decode("latin1").encode("utf-8")

In [14]: c
Out[14]: b'clich\xc3\x83\xc2\xa9'

答案 1 :(得分:1)

原始文本以utf-8编码,但有些进程将其解码为latin1,然后再将其编码为utf-8。

因此,要获得原始文本,您必须撤消此过程:您将文件中的文本解码为utf-8(这不包含在您的代码段中,但我猜您使用utf-8编码打开它),然后对其进行编码作为latin1,然后再次解码为utf-8。

答案 2 :(得分:0)

从您的评论中,您说您在Python 3中打开文本文件而未指定任何编码。在这种情况下,Python使用系统编码,即Windows上的Latin1。

这足以解释如果文件最初是utf8编码的话会得到什么。但恕我直言,正确的方法是在open函数中指定文件编码:

fd = open(filename, encoding='utf8')

这样,您可以直接获得正确的字符,而无需进行编码 - 解码校正。