视窗控制台编码



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)。

相关内容

最新更新