为什么Python无法识别我的UTF-8编码的源文件?

21

这里有一个带有非ASCII字符的小tmp.py文件:

if __name__ == "__main__":
    s = 'ß'
    print(s)

运行它时,我得到了以下错误:

Traceback (most recent call last):
  File ".\tmp.py", line 3, in <module>
    print(s)
  File "C:\Python32\lib\encodings\cp866.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_map)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\xdf' in position 0: character maps to <undefined>

Python文档指出

默认情况下,Python源文件被视为以UTF-8编码...

我检查编码的方法是使用Firefox(也许有人会建议更明显的方法)。我在Firefox中打开tmp.py,如果我选择查看->字符编码->Unicode(UTF-8),它看起来很好,就像这个问题上面的样子(带ß符号)。

如果我放置:

# -*- encoding: utf-8 -*-

作为 tmp.py 中的第一个字符串,它并没有改变任何东西 - 错误仍然存在。
有人能帮我找出我做错了什么吗?

1
@Blender:在Python 3中,u没有任何作用(在早期版本的Python 3中是一个错误,直到为了向后兼容而被添加回来)。 - Wooble
很可能是您在编辑器中设置编码的问题。 - LtWorf
2
同时它显示编码错误,而不是解码错误。由于cp866是ms-dos代码页,我认为您正在尝试将其打印到控制台,这需要进行编码。 - Esailija
@Wooble,你能解释一下如何确定吗?如果我使用Firefox技巧,选择ISO 8859-1,我会看到s ='ß'而不是s='ß' - Anton Daneyko
@mezhaka:我错了,Martijn 给出了正确的解释。 - Wooble
1个回答

36
您的终端所使用的编码不支持该字符:

请参考代码页 866了解更多信息:

>>> '\xdf'.encode('cp866')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/encodings/cp866.py", line 12, in encode
    return codecs.charmap_encode(input,errors,encoding_map)
UnicodeEncodeError: 'charmap' codec can't encode character '\xdf' in position 0: character maps to <undefined>

Python可以很好地处理它,问题出在你的输出编码方式无法处理它。

你可以尝试在Windows控制台中使用chcp 65001切换代码页;chcp是一个Windows命令行命令,用于更改代码页。

我在OS X上使用UTF-8可以很好地处理它:

>>> print('\xdf')
ß

1
如果他在运行程序之前执行 chcp 65001,假设 Python 检测到,那么他在 Windows 上应该没问题。 - Esailija
6
没错,这个问题与终端相关。如果我使用 with open('tmp.txt', 'w', encoding='utf-8') as f: f.write(s) 就可以正常工作。您能解释一下“尝试使用 chcp 65001”吗?对我来说这并没有说明任何事情。 - Anton Daneyko
@mezhaka:是的,重定向到文件意味着没有为打印(写入sys.stdout)设置编码。在这种情况下需要手动编码。而且你的终端字体不支持你尝试打印的字符,所以它们无法正确显示。 - Martijn Pieters
正确的解决方案是保持 chcp 不变,并在 Windows 上使用 Unicode API。 - jfs
@J.F.Sebastian:我同意;我已经将关于Windows控制台打印的问题转到了那篇帖子上,数量相当多了。 - Martijn Pieters
显示剩余7条评论

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