Windows 上的默认控制台编码是什么?似乎有时是ANSI 编码(CP-1252),有时是chcp
命令给出的OEM 编码(默认情况下为西欧的 CP-850)。
-
命令行参数和环境变量触发 ANSI 编码 (
é
= 0xe9):> chcp 850 Active code page: 850 > python -c "print 'é'" Ú > python -c "print 'x82'" é > python -c "print 'xe9'" Ú > $env:foobar="é"; python -c "import os; print os.getenv('foobar')" Ú > chcp 1252 Active code page: 1252 > python -c "print 'é'" é > python -c "print 'x82'" , > python -c "print 'xe9'" é > $env:foobar="é"; python -c "import os; print os.getenv('foobar')" é
-
Python 控制台和标准输入触发 OEM 编码(如果 OEM 编码为 CP-850,则
é
= 0x82,如果 OEM 编码为 CP-1252,则é
= 0xe9):> chcp 850 Active code page: 850 > python >>> print 'é' é >>> print 'x82' é >>> print 'xe9' Ú > python -c "print raw_input()" é é > chcp 1252 Active code page: 1252 > python >>> print 'é' é >>> print 'x82' , >>> print 'xe9' é > python -c "print raw_input()" é é
注意:在这些例子中,我在Windows 10上使用Powershell 5.1和CPython 2.7.14。
首先,对于所有非ASCII字符,这里重要的是您的控制台编码和Windows语言环境设置,您使用的是字节字符串,而Python只是打印出它收到的字节。您的键盘输入由控制台编码为特定的字节或字节序列,然后再将这些字节传递给 Python。对于 Python 来说,这只是不透明的数据(0-255 范围内的数字),print
以 Python 接收它们的方式将这些数据传回控制台。
在 Powershell 中,用于通过命令行开关发送到 Python 的字节的编码不是由chcp
代码页确定的,而是由控制面板中的">非 Unicode 程序的语言"设置确定的(搜索">区域",然后找到">管理"选项卡)。正是此设置将é
编码为0xE9,然后再将其作为命令行参数传递给 Python。有大量的 Windows 代码页使用 0xE9 进行é
(但没有 ANSI 编码这样的东西)。
这同样适用于环境变量。Python 将 Windows 在这里使用的编码称为 MBCS 编解码器;您可以使用带有CP_ACP
标志的'mbcs'
编解码器将命令行参数或环境变量解码为 Unicode,该编解码器使用MultiByteToWideChar()
和WideCharToMultiByte()
Windows API 函数。
使用交互式提示时,Python 将按照 Powershell 控制台区域设置代码页的编码传递字节,并使用chcp
进行设置。对于您来说,这是代码页 850,当您键入é
时,会收到一个带有十六进制值 0x82 的字节。由于print
将相同的0x82字节发送回同一控制台,因此控制台随后会将0x82转换回屏幕上的é
字符。
只有当你使用Unicode文本(带有像u'é'
这样的Unicode字符串文字)时,Python才会对数据进行任何解码和编码。print
写入sys.stdout
,该 配置为将 Unicode 数据编码为当前语言环境(如果已设置,则PYTHONIOENCODING
),因此print u'é'
会将该 Unicode 对象写入sys.stdout
,然后使用配置的编解码器将该对象编码为字节,然后将这些字节写入控制台。
为了从u'é'
源代码文本(本身就是一个字节序列)生成unicode
对象,Python 必须解码给定的源代码。对于-c
命令行,传入的字节将解码为 Latin-1。在交互式控制台中,使用区域设置。因此,交互式会话中的python -c "print u'é'"
和print u'é'
将导致不同的输出。
应该注意的是,Python 3 自始至终使用 Unicode 字符串,命令行参数和环境变量使用 Windows"宽"API 加载到 Python 中,以 UTF-16 形式访问数据,然后呈现为 Unicode 字符串对象。您仍然可以以字节字符串的形式访问控制台数据和文件系统信息,但从 Python 3.6 开始,以二进制形式访问文件系统和 stdin/stdout/stderr 流使用 UTF-8 编码数据(再次使用"宽"API)。