gpt4 book ai didi

python - chcp 65001 代码页导致程序终止而没有任何错误

转载 作者:可可西里 更新时间:2023-11-01 13:53:14 24 4
gpt4 key购买 nike

问题
当我想在 Python 解释器中输入 Unicode 字符时出现问题(为简单起见,我在示例中使用了 a-umlaut,但我第一次遇到波斯字符)。每当我将 python 与 chcp 65001 代码页一起使用,然后尝试输入一个 Unicode 字符时,Python 都会退出而不会出现任何错误。

我花了几天时间试图解决这个问题,但没有成功。但是今天,我在 python website 上发现了一个话题, 另一个在 MySQL另一个关于 Lua 用户关于这个突然退出提出的问题,尽管没有任何解决方案并且有人说 chcp 65001 本身就坏了。

最好一劳永逸地知道这个问题是与 chcp 设计相关还是有可能的解决方法。

重现错误

chcp 65001

Python 3.X:

Python 外壳

print('ä')

结果:它只是退出了 shell

但是,这有效 python.exe -c "p​​rint('ä')"还有这个:print('\u00e4')

结果:ä

in Luajit2.0.4

print('ä')

结果:它只是退出了 shell

然而这是可行的:print('\xc3\xa4')

到目前为止,我得出了这个观察结果:

  1. 使用命令提示符直接输出是可行的。
  2. 基于 Unicode 和基于十六进制的字符等效项。

所以 这不是 Python 错误并且我们不能在 Windows 命令提示符或任何它的 Wrapper 中直接在 CLI 程序中使用 Unicode 字符,如 Conemu、Cmder(我使用 Cmder 能够看到并在 Windows shell 中使用 Unicode 字符,我这样做没有任何问题)。这是正确的吗?

最佳答案

要在 Python 2.7 和 3.x(3.6 之前)的 Windows 控制台中使用 Unicode,请安装并启用 win_unicode_console .这使用宽字符函数 ReadConsoleWWriteConsoleW ,就像其他支持 Unicode 的控制台程序(例如 cmd.exe 和 powershell.exe)一样。对于 Python 3.6,添加了一个新的 io._WindowsConsoleIO 原始 I/O 类。它读取和写入 UTF-8 编码的文本(为了与 Unix 的跨平台兼容性——“获取一个字节”——程序),但在内部它通过与 UTF-16LE 之间的代码转换使用宽字符 API。

您遇到的非 ASCII 输入问题在所有 Windows 版本(包括 Windows 10)的控制台中都可以重现。控制台主机进程,即 conhost.exe,不是为 UTF-8 设计的(代码页65001) 并且尚未更新以始终支持它。特别是,非 ASCII 输入会导致空读取。这反过来会导致 Python 的 REPL 退出并内置 input 引发 EOFError

问题在于 conhost 假定单字节代码页对其 UTF-16 输入缓冲区进行编码,例如西方语言环境中的 OEM 和 ANSI 代码页(例如 437、850、1252)。 UTF-8 是一种多字节编码,其中非 ASCII 字符被编码为 2 到 4 个字节。要处理 UTF-8,它需要在 M/4 字符的多次迭代中进行编码,其中 M 是 N 字节缓冲区中可用的剩余字节。相反,它假定读取 N 个字节的请求是读取 N 个字符的请求。然后,如果输入有一个或多个非 ASCII 字符,内部 WideCharToMultiByte 调用会因缓冲区过小而失败,并且控制台会返回“成功”读取 0 字节。

如果安装了 pyreadline 模块,您可能无法在 Python 3.5 中准确观察到此问题。 Python 3.5 自动尝试导入 readline。在 pyreadline 的情况下,输入是通过宽字符函数 ReadConsoleInputW 读取的。 .这是读取控制台输入记录的低级函数。原则上它应该有效,但实际上输入 print('ä') 会被 REPL 读取为 print('')。对于非 ASCII 字符,ReadConsoleInputW 返回一系列 Alt+Numpad KEY_EVENT 记录。该序列是有损 OEM 编码,除了最后一条记录外可以忽略,该记录在 UnicodeChar 字段中具有输入字符。显然 pyreadline 忽略了整个序列。

在 Windows 8 之前,使用代码页 65001 的输出也被破坏。它会打印出与非 ASCII 字符数量成比例的垃圾文本。在这种情况下,问题是 WriteFileWriteConsoleA 错误地返回了写入屏幕缓冲区的 UTF-16 代码数,而不是 UTF-8 字节数。这会混淆 Python 的缓冲写入器,导致重复写入它认为是剩余未写入字节的内容。作为重写内部控制台 API 以使用 ConDrv 设备而不是 LPC 端口的一部分,此问题已在 Windows 8 中得到修复。旧版本的 Windows 可以使用 ConEmu 或 ANSICON 来解决此错误。

关于python - chcp 65001 代码页导致程序终止而没有任何错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39736901/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com