【问题标题】:Python understanding unicode conversionPython理解unicode转换
【发布时间】:2016-12-12 13:14:20
【问题描述】:

我有一个文本数据集,其中存在一些编码问题。 作者指示这样做:

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。

这有点道理,但我无法建立联系。

原文件中的行到底是怎么存储的,sn-p代码是怎么修复的?

【问题讨论】:

  • 你用的是什么版本的Python(Python2或Python3),原文件是如何打开的?
  • @SergeBallesta 我使用的是python 3,原始文件以读取模式打开,没有指定编码。

标签: python unicode python-unicode


【解决方案1】:

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

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

修复的作用是:您的系统设置已配置为以 utf-8 格式读取文本 - 因此,当您在 for 循环中获得这些行时,您会得到 Python-3 字符串(Python-2 unicode)正确解释为 UTF-文本文件中的 8 个字符。所以 4 字节序列变成了 2 个文本字符。现在,“latin1”编码的一个特点是它是“透明的”:它相当于对文本字节完全不进行任何转换。换句话说,在 Python 的 Unicode 内部表示中,由适合单个字节的值表示的每个字符都将成为编码字节字符串中的单个字节。 (并且值不适合一个字节的每个字符根本不能编码为 Latin-1,从而产生 Unicode-Encode 错误)。

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

再次:

这是原文: “陈词滥调”。编码为 UTF-8 就变成了这样: b'陈词滥调\xc3\xa9' 但是创建文件的原始过程将此序列视为 latin-1,因此将两个 > 0x80 字符重新转换为 utf-8: b'陈词滥调\xc3\x83\xc2\xa9'。 这就是“陈词滥调”

在阅读时,Python3 读取: b'clich\xc3\x83\xc2\xa9' 从磁盘返回,并以(unicode)文本形式返回给您“cliché”。 您将其编码为字节,并通过调用“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'

【讨论】:

    【解决方案2】:

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

    所以要得到原始文本,你必须颠倒这个过程:你将文件中的文本解码为 utf-8(这不包含在你的 sn-p 中,但我猜你用 utf-8 编码打开它),然后将其编码为 latin1,然后再次解码为 utf-8。

    【讨论】:

      【解决方案3】:

      从您的评论中,您说您正在 Python 3 中打开一个文本文件,但没有指定任何编码。在这种情况下,Python 使用 system 编码,在 Windows 上是 Latin1。

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-10
        • 2018-08-16
        • 1970-01-01
        • 2011-06-12
        • 1970-01-01
        • 1970-01-01
        • 2011-05-29
        • 2013-05-17
        相关资源
        最近更新 更多