【问题标题】:Python encoding declaration appears to be getting ignored?Python 编码声明似乎被忽略了?
【发布时间】:2017-10-26 14:44:11
【问题描述】:

以下代码保存为 utf-8 编码的文本文件:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
print 'é'

当我使用 Python 2.7 在 Linux 的命令行上运行上述代码时,我得到了预期的输出 é

如果我将文件中的编码声明从 utf-8 更改为 cp1252 并重新运行它,我会得到相同的输出 é

但是Python现在不应该将文件中的é解释为十六进制c3a9,作为cp1252编码文本吗?在这种情况下,输出应该是é

如果我强制我的文本编辑器将文件作为 cp1252 编码文本查看,é 将更改为 é。为什么 Python 不做同样的事情?

【问题讨论】:

  • 我无法重现此内容。更改编码指令确实会为我更改程序的输出。但是,您忽略了设置中的一个未知因素,即程序输出的解释和呈现方式。也许这有帮助......

标签: python character-encoding


【解决方案1】:

当我们声明 # -*- coding: ... -*-(或只是 # coding: ...)时,我们是在告诉 Python 源文件保存在声明的编码中。
因此,编码声明很重要,但是在源文件在声明的编码中有效并且我们不使用u-literals 之前,更改声明的编码不会影响打印输出。

要检查最后一条语句,让我们看一下:


编码声明的效果。

1.语法错误测试。

首先,Python 使用 SyntaxError 测试的声明编码。
例如,让我们运行以下保存在utf-8中的源文件:

# -*- coding: utf-8 -*-
print repr('Á') # '\xc3\x81'

从打印输出中可以看出:Á 字符的 utf-8 字节为:\xc3\x81
让我们更改声明的编码并再次运行文件:

# -*- coding: cp1252 -*-
print repr('Á')

现在它失败并出现错误:

SyntaxError: 'charmap' codec can't decode byte 0x81 in position 13: character maps to <undefined>

源仍在utf-8 中,但现在\xc3\x81 字节序列在声明的编码(cp1252)中无效,因为在此编码中\x81 字节映射到UNDEFINED


同时é 字符的utf-8 字节为:\xc3\xa9,此字节序列在cp1252 中有效。因此,在这种情况下,声明哪种编码并不重要——utf-8cp1252——上面提到的字节将通过SyntaxError 测试:

# -*- coding: utf-8 -*-
print repr('é') # '\xc3\xa9'
# -*- coding: cp1252 -*-
print repr('é') # '\xc3\xa9'

然后它们将通过sys.stdout.encoding:
打印/解码 (大约如下例所示)

import sys
bytes_in = '\xc3\xa9'
enc_out = sys.stdout.encoding
chars_out = '\xc3\xa9'.decode(enc_out)
print chars_out # 'é' if enc_out == 'utf-8'

sys.stdout.encoding 取决于环境,不取决于声明的编码。
这就是为什么当源文件采用相同编码时,您会得到相同的输出。


2. Unicode字面量解读

但是,编码声明会影响 Python 如何解释使用 u-literals 声明的 unicode 字符串:

# -*- coding: utf-8 -*-
print repr(u'é') # u'\xe9'
# -*- coding: cp1252 -*-
print repr(u'é') # u'\xc3\xa9'

在最后一个示例中,Python 将u'é' 解释为
\xc3\xa9 字节到cp1252 编码解码的unicode-string

print repr(unicode('\xc3\xa9', 'cp1252')) # u'\xc3\xa9'

让我们打印这个 unicode 字符串:

print unicode('\xc3\xa9', 'cp1252') # é

因此,在源文件位于utf-8 且声明的编码为cp1252 的情况下,您可以使用é 的unicode-literal 获得é 输出:

# -*- coding: cp1252 -*-
print u'é' # é

有关更多信息,您可以查看以下内容:

  • PEP 263 -- Defining Python Source Code Encodings
  • The source of Python's tokenizer function
  • 【讨论】:

    • 非常详细且内容丰富的答案。我实际上输入了您提供的所有示例,这确实有助于我理解该主题。干得好:)
    猜你喜欢
    • 2021-10-28
    • 2016-09-30
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    • 2017-12-05
    • 2012-03-08
    • 2015-12-11
    相关资源
    最近更新 更多