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

chcp 65001代码页导致程序终止,没有任何错误,第1张

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

要在Windows控制台中使用Python
2.7和3.x(3.6之前)的Unipre,请安装并启用win_unipre_console。像其他cmd.exe和powershell.exe这样的可识别Unipre的控制台程序一样,它使用宽字符函数

ReadConsoleW
WriteConsoleW
。对于Python 3.6,添加了新的
io._WindowsConsoleIO
原始I /
O类。它读取和写入UTF-8编码的文本(为了与Unix跨平台兼容-“获取字节”-程序),但是在内部它通过与UTF-16LE进行代码转换来使用宽字符API。

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

input
来引发
EOFError

问题是conhost假设单字节代码页(例如西方语言环境中的OEM和ANSI代码页)(例如437、850、1252),对UTF-16输入缓冲区进行编码。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编码,除了最后一条记录(该记录在
UnipreChar
字段中具有输入字符)外,可以忽略。显然pyreadline忽略了整个序列。

在Windows
8之前,使用代码页65001的输出也已损坏。它按与非ASCII字符数成比例的方式打印一堆垃圾文本。在这种情况下的问题是,

WriteFile
WriteConsoleA
错误地返回的写入屏幕缓冲液代替的UTF-8字节数UTF-16码的数目。这使Python的缓冲编写器感到困惑,导致重复写入它认为剩余的未写入字节。在Windows
8中,此问题已得到解决,这是重写内部控制台API以使用ConDrv设备而不是LPC端口的一部分。较早版本的Windows可以使用ConEmu或ANSICON来解决此错误。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5647035.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存