请帮助我理解为什么Unicode有时只适用于Python

请帮助我理解为什么Unicode有时只适用于Python,python,unicode,windows-7,ubuntu,ipython,Python,Unicode,Windows 7,Ubuntu,Ipython,这里有一个小程序: #!/usr/bin/env python # -*- encoding: utf-8 -*- print('abcd kΩ ☠ °C √Hz µF ü ☃ ♥') print(u'abcd kΩ ☠ °C √Hz µF ü ☃ ♥') 在Gnome终端Ubuntu上,IPython实现了我所期望的: In [6]: run Unicodetest.py abcd kΩ ☠ °C √Hz µF ü ☃ ♥ abcd kΩ ☠ °C √Hz µF ü ☃ ♥ 如果在上

这里有一个小程序:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

print('abcd kΩ ☠ °C √Hz µF ü ☃ ♥')  
print(u'abcd kΩ ☠ °C √Hz µF ü ☃ ♥')
在Gnome终端Ubuntu上,IPython实现了我所期望的:

In [6]: run Unicodetest.py
abcd kΩ ☠ °C √Hz µF ü ☃ ♥
abcd kΩ ☠ °C √Hz µF ü ☃ ♥
如果在上输入命令,则得到相同的输出

另一方面,为第二个命令生成错误:

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命令提示符下或通过Python(x,y)的Console2版本中的IPython都会损坏第一个输出,并抱怨第二个输出:

>>>
abcd kΩ ☠ °C √Hz µF ü ☃ ♥
abcd kΩ ☠ °C √Hz µF ü ☃ ♥
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>
[9]中的
:运行Unicodetest.py
abcd k╬⌐ Γÿá ┬░CΓÜHz┬╡F├╝ Γÿâ ΓÖÑ
错误:标记输入时发生意外错误
以下回溯可能已损坏或无效
错误消息是:('EOF in multi-line statement',(15,0))
---------------------------------------------------------------------------
UnicodeEncodeError回溯(最近一次呼叫最后一次)
桌面\Unicodetest.py在()
4打印('k╬⌐ Γÿá ┬░CΓÜHz┬╡F├╝ Γÿâ ΓÖÑ')
5.
---->6打印(u'k)╬⌐ Γÿá ┬░CΓÜHz┬╡F├╝ Γÿâ ΓÖÑ')
7.
8.
C:\Python27\lib\encodings\cp437.pyc in encode(self、input、errors)
10
11 def编码(自身、输入、错误='strict'):
--->12返回编解码器。字符映射编码(输入、错误、编码映射)
13
14 def解码(自身、输入、错误='strict'):
UnicodeEncodeError:“charmap”编解码器无法对位置8中的字符u'\u2620'进行编码:字符映射到
警告:执行文件失败:
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>
[8]中的
:运行Unicodetest.py
abcd kÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎΙ¥
------------------------------------------------------------
回溯(最近一次呼叫最后一次):
文件“Unicodetest.py”,第6行,在
印刷(u'abcd kÎ)–C–ˆšHzµFü–ƒ)™¥')
文件“C:\Python26\lib\encodings\cp1252.py”,第12行,在encode中
返回codecs.charmap\u encode(输入、错误、编码表)
UnicodeEncodeError:“charmap”编解码器无法对位置6中的字符u'\u03a9'进行编码:字符映射到
警告:执行文件失败:
(在中,Spyder根据区域设置模块的编码设置自己的
Spyder_编码
,即Windows 7的
cp1252
。)

有什么好处?我的命令有错吗?为什么一个在某些平台上工作,而另一个在其他平台上工作?如何始终如一地打印Unicode字符而不崩溃或出错


Windows是否有一个类似Ubuntu的备用终端?似乎TCC-LE、Console2、Git Bash、PyCmd等都只是cmd.exe的包装,而不是替代品。有没有办法在IDLE使用的界面内运行IPython?

您的问题是,您的程序需要并输出UTF-8字符,但控制台和web上的各种python运行程序使用其他代码页没有办法不经修改就对所有编码中的特殊字符进行编码。但是,如果您选择在任何地方使用UTF-8,您应该是安全的

我认为Windows中的任何终端都可以,所以不要因为这个而麻烦地切换默认终端(cmd.exe)。相反,将终端的编码也更改为UTF-8,以匹配python脚本的编码

不幸的是,我一直无法找到将代码页设置为UTF-8作为默认值的方法,因此每次打开新的命令提示符时都必须这样做。但它是通过一个简单的命令完成的,所以它只有一半坏。。。您可以通过以下方式更改编码:


请注意,您必须使用其中一种标准字体才能工作。网络上的大多数来源似乎都建议使用Lucida控制台。

可能有两个原因:

  • 通过
    print
    对Unicode进行编码。您无法输出原始Unicode,因此,
    print
    需要弄清楚如何将其转换为控制台所期望的字节流(它使用
    sys.stdout.encoding
    AFAIK),这就带来了
  • 控制台支持。Python不控制您的终端,因此,如果它在您的终端需要其他东西时吐出UTF-8,您将得到混乱的输出

从Python到Windows控制台的Unicode输出根本不起作用。无法说服Python发出本机Windows编码,因为它需要宽字符和UCS2。

Python(以及大多数其他语言)中的I/O是基于字节的。当您将字节字符串(2.x中的
str
,3.x中的
bytes
)写入文件时,字节只需按原样写入即可。将Unicode字符串(
Unicode
in 2.x,
str
in 3.x)写入文件时,需要将数据编码为字节序列

有关此区别的进一步解释,请参阅

这里,字符串是一个字节字符串。因为源文件的编码是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”代码页中编码,而在美国是这样。所以你在屏幕上看到的字符串是

abcd kΩ ☠ °C √Hz µF ü ☃ ♥
在Ubuntu系统上,这不会导致问题,因为默认的控制台编码是UTF-8,所以源文件编码和控制台编码之间没有差异

print(u'abcd kΩ ☠ °C √Hz µF ü ☃ ♥')
打印Unicode字符串时,必须将字符串编码为字节。但只有当您有支持这些字符的编码时,它才起作用。而你没有

  • 默认的IBM437编码缺少字符
    ☠☃♥
  • Spyder使用的编码缺少字符
    Ω☠√☃♥
因此,在这两种情况下,您在打印字符串时都会遇到一个UnicodeError

有什么好处

Windows和Linux采用了截然不同的方法来支持Unicode

最初,它们的工作方式基本相同:每个语言环境都有自己的基于特定语言的
char
编码(“ANSI代码p
abcd kΩ ☠ °C √Hz µF ü ☃ ♥
print(u'abcd kΩ ☠ °C √Hz µF ü ☃ ♥')
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);