【问题标题】:Windows console encodingWindows 控制台编码
【发布时间】:2018-08-13 18:48:18
【问题描述】:

Windows 上的默认控制台编码是什么?有时它似乎是 ANSI 编码 (CP-1252),有时它是由@987654323 给出的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 编码(é = 0x82 如果 OEM 编码是 CP-850,é = 0xe9 如果 OEM 编码是 CP-1252):

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

【问题讨论】:

    标签: python python-2.7 character-encoding windows-console


    【解决方案1】:

    首先,对于所有非 ASCII 字符,这里重要的是您的控制台编码和 Windows 区域设置,您使用的是 字节字符串,而 Python 只是打印出它收到的字节。在将这些字节传递给 Python 之前,您的键盘输入会被控制台编码为特定的字节或字节序列。对 Python 来说,这只是不透明的数据(0-255 范围内的数字),print 将这些数据传回控制台,就像 Python 接收它们一样。

    在 Powershell 中,通过命令行开关发送到 Python 的字节使用什么编码不是由 chcp 代码页决定,而是由 非 Unicode 程序的语言 设置决定控制面板(搜索 Region,然后找到 Administrative 选项卡)。 此设置é 编码为 0xE9,然后将其作为命令行参数传递给 Python。有a large number of Windows codepages 使用0xE9 表示é(但也有no such thing as an ANSI encoding)。

    这同样适用于环境变量。 Python 将 Windows 在这里使用的编码称为MBCS codec;您可以使用'mbcs' 编解码器将命令行参数或环境变量解码为Unicode,该编解码器使用MultiByteToWideChar()WideCharToMultiByte() Windows API 函数以及CP_ACP 标志。

    使用交互式提示时,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 命令行,在are decoded as Latin-1 中传递的字节。在交互式控制台中,使用区域设置。所以python -c "print u'é'"print u'é'在交互会话中会产生不同的输出。

    需要注意的是,Python 3 始终使用 Unicode 字符串,命令行参数和环境变量通过 Windows 'wide' API 加载到 Python 中,以 UTF-16 格式访问数据,然后以 Unicode 字符串对象的形式呈现。您仍然可以以字节字符串的形式访问控制台数据和文件系统信息,但从 Python 3.6 开始,accessing the filesystem and stdin/stdout/stderr streams as binary uses UTF-8 encoded data(再次使用“宽”API)。

    【讨论】:

    • 谢谢。我已经更新了我的问题以包含一个带有环境变量的示例,并将 xxd(Vim 中包含的十六进制转储程序)示例替换为纯 Python 示例。
    • @Maggyero:请不要移动球门柱。 Windows 使用与命令行参数相同的编解码器将环境变量传递给进程。
    • 很好的编辑,我会接受你的回答,但在我需要完成一些测试(以确保我理解所有内容)之前,也许要编辑你的帖子中我没有马上得到的部分.
    • 您在第二段中所说的chg 代码页是什么?是不是笔误?
    • Windows 本身仅使用 Unicode 命令行和进程环境块 (PEB) 中的环境来执行进程。 Python 2 依赖进程内 C 运行时库来解析/提供来自 GetCommandLineAGetEnvironmentStringsA 的旧版 ANSI 编码命令行和环境。您可以安装 win_unicode_console 以使用控制台的 Unicode 接口,并将 sys.argv 替换为来自本机 Unicode 命令行的解析参数。
    猜你喜欢
    • 2013-06-28
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    • 2018-03-25
    相关资源
    最近更新 更多