这是一个小程序:
#!/usr/bin/env python # -*- encoding: utf-8 -*- print('abcd kΩ ☠ °C √Hz µF ü ☃ ♥') print(u'abcd kΩ ☠ °C √Hz µF ü ☃ ♥')
在Ubuntu上,Gnometerminal,IPython做我所期望的:
In [6]: run Unicodetest.py abcd kΩ ☠ °C √Hz µF ü ☃ ♥ abcd kΩ ☠ °C √Hz µF ü ☃ ♥
如果我在trypython.org上input命令,我会得到相同的输出。
另一方面, codepad.org会为第二个命令产生一个错误:
abcd kΩ ☠ °C √Hz µF ü ☃ ♥ Traceback (most recent call last): Line 6, in <module> print(u'abcd kΩ ☠ °C √Hz µF ü ☃ ♥') UnicodeEncodeError: 'ascii' codec can't encode character u'\u03a9' in position 6: ordinal not in range(128)
相反,Windows上的IDLE会破坏第一个命令的输出,但不会抱怨第二个命令:
>>> abcd kΩ ☠°C √Hz µF ü ☃ ♥ abcd kΩ ☠ °C √Hz µF ü ☃ ♥
IPython在Windows命令提示符下或者通过Python(x,y)的Console2版本都会破坏第一个输出并抱怨第二个输出:
In [9]: run Unicodetest.py abcd kΩ ☠ °C √Hz µF ü ☃ ♥ ERROR: An unexpected error occurred while tokenizing input The following traceback may be corrupted or invalid The error message is: ('EOF in multi-line statement', (15, 0)) --------------------------------------------------------------------------- UnicodeEncodeError Traceback (most recent call last) Desktop\Unicodetest.py in <module>() 4 print('abcd kΩ ☠ °C √Hz µF ü ☃ ♥') 5 ----> 6 print(u'abcd kΩ ☠ °C √Hz µF ü ☃ ♥') 7 8 C:\Python27\lib\encodings\cp437.pyc in encode(self, input, errors) 10 11 def encode(self,input,errors='strict'): ---> 12 return codecs.charmap_encode(input,errors,encoding_map) 13 14 def decode(self,input,errors='strict'): UnicodeEncodeError: 'charmap' codec can't encode character u'\u2620' in position 8: character maps to <undefined> WARNING: Failure executing file: <Unicodetest.py>
Python(x,y)的Spyder中的IPython也是一样的,但不同的是:
In [8]: run Unicodetest.py abcd kΩ ☠°C √Hz µF ü ☃ ♥ ------------------------------------------------------------ Traceback (most recent call last): File "Unicodetest.py", line 6, in <module> print(u'abcd kΩ ☠°C √Hz µF ü ☃ ♥') File "C:\Python26\lib\encodings\cp1252.py", line 12, in encode return codecs.charmap_encode(input,errors,encoding_table) UnicodeEncodeError: 'charmap' codec can't encode character u'\u03a9' in position 6: character maps to <undefined> WARNING: Failure executing file: <Unicodetest.py>
(在sitecustomize.py中 ,Spyder根据语言环境模块的编码设置自己的SPYDER_ENCODING
,这是Windows 7的cp1252
)
是什么赋予了? 我的一个命令是错的吗? 为什么在一些平台上工作而另一个平台上工作呢? 如何一致地打印Unicode字符而不会崩溃或搞砸?
是否有一个替代的terminalWindows的行为就像在Ubuntu中的? 看来TCC-LE,Console2,Git Bash,PyCmd等都只是cmd.exe的包装,而不是替代品。 有没有办法在IDLE使用的界面内运行IPython?
Python(和大多数其他语言)中的I / O是基于字节的 。 当您将一个字节字符串(2.x中的str
,3.x中的字节)写入文件时,字节将按原样写入。 当您将Unicode字符串(2.x中的unicode
,3.x中的str
)写入文件时,需要将数据编码为一个字节序列。
有关这个区别的进一步解释,请参阅关于字符串的Dive into Python 3章节 。
print('abcd kΩ ☠ °C √Hz µF ü ☃ ♥')
这里的字符串是一个字节字符串。 由于您的源文件的编码是UTF-8,字节是
'abcd k\xce\xa9 \xe2\x98\xa0 \xc2\xb0C \xe2\x88\x9aHz \xc2\xb5F \xc3\xbc \xe2\x98\x83 \xe2\x99\xa5'
print
语句将这些字节按原样写入控制台。 但Windows控制台将字节字符串解释为在“OEM”代码页中进行编码,在美国是437 。 所以你在屏幕上看到的字符串是
abcd kΩ ☠ °C √Hz µF ü ☃ ♥
在你的Ubuntu系统上,这不会引起问题,因为默认的控制台编码是UTF-8,所以你没有源文件编码和控制台编码之间的差异。
print(u'abcd kΩ ☠ °C √Hz µF ü ☃ ♥')
打印Unicode字符串时,字符串必须被编码为字节。 但是只有在支持这些字符的编码时才有效。 而你没有。
☠☃♥
Ω☠√☃♥
。 所以,在这两种情况下,你都会得到一个UnicodeEncodeError试图打印字符串。
是什么赋予了?
Windows和Linux采用完全不同的方法来支持Unicode。
最初,它们的工作方式几乎相同:每个语言环境都有自己的特定于语言的基于char
的编码(Windows中的“ANSI代码页”)。 西方语言使用ISO-8859-1或Windows-1252,俄语使用KOI8-R或Windows-1251等。
当Windows NT添加对Unicode的支持时(int在早期假定Unicode将使用16位字符时),它通过创建使用wchar_t
而不是char
API的并行版本来实现。 例如, MessageBox函数被分成两个函数:
int MessageBoxA(HWND hWnd, const char* lpText, const char* lpCaption, unsigned int uType); int MessageBoxW(HWND hWnd, const wchar_t* lpText, const wchar_t* lpCaption, unsigned int uType);
“W”功能是“真正的”功能。 “A”功能是为了与基于DOS的Windows向后兼容而存在的,主要是将它们的字符串参数转换为UTF-16,然后调用相应的“W”函数。
在Unix世界(特别是Plan 9)中,编写全新版本的POSIX API被认为是不切实际的,所以Unicode支持以不同的方式接近。 在CJK语言环境中,现有的对多字节编码的支持被用来实现现在称为UTF-8的新编码。
在类Unix系统上使用UTF-8和在Windows上使用UTF-16时,对于编写支持Unicode的跨平台代码来说,这是一个巨大的麻烦。 Python试图从程序员那里隐藏这一点,但是打印到控制台是Joel的“泄漏抽象”之一。
有两个可能的原因:
print
编码Unicode。 你不能输出原始的Unicode,所以print
需要弄清楚如何将其转换为控制台所期望的字节流(它使用sys.stdout.encoding
AFAIK),这使我们 你的问题在于你的程序需要输出UTF-8字符,但是Web上的控制台和各种python运行器使用其他代码页。 没有办法编码在所有编码中工作的特殊字符而无需修改。 但是,如果您选择在任何地方使用UTF-8,则应该是安全的。
我认为在Windows中的任何终端将做 – 所以不要打扰切换出来的默认(cmd.exe),正因为如此。 相反,更改终端的编码为UTF-8,以匹配您的Python脚本的编码。
不幸的是,我从来没有找到一种方法将代码页设置为默认的UTF-8,所以每次打开新的命令提示符时都必须完成。 但是,它是通过一个简单的命令完成的,所以它只是一半坏的…您通过切换代码页来更改编码:
>chcp 65001 Current codepage is now 65001
请注意,您必须使用其中一种标准字体才能正常工作。 网络上的大多数消息来源似乎都暗示了Lucida Console。
从Python到Windows控制台的Unicode输出不起作用。 Python不能被说服发出预期宽字符和UCS2的本机Windows编码。
@ dan04:你说得对,问题是文件的编码与stdout的编码不匹配。 尽管如此,解决该问题的一种方法是更改文件的编码。 所以在Windows上,Notepad ++可以用UTF-8字符编码保存代码。
另一种方法是GNU recode。