您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

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

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

要在Windows控制台中使用Python 2.7和3.x(3.6之前)的Unicode,请安装并启用@L_403_0@。像其他cmd.exe和powershell.exe这样的可识别Unicode的控制台程序一样,它使用宽字符函数ReadConsoleWWriteConsoleW。对于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 + NumpadKEY_EVENT记录序列。该序列是有损的OEM编码,除了最后一条记录(该记录在UnicodeChar字段中具有输入字符)外,可以忽略。显然pyreadline忽略了整个序列。

在Windows 8之前,使用代码页65001的输出也已损坏。它按与非ASCII字符数成比例的方式打印一堆垃圾文本。在这种情况下的问题是,WriteFileWriteConsoleA错误地返回的写入屏幕缓冲液代替的UTF-8字节数UTF-16码的数目。这使Python的缓冲编写器感到困惑,导致重复写入它认为剩余的未写入字节。在Windows 8中,此问题已得到解决,这是重写内部控制台API以使用ConDrv设备而不是LPC端口的一部分。较早版本的Windows可以使用ConEmu或ANSICON来解决错误

其他 2022/1/1 18:25:24 有449人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶