当前位置: 首页 > 面试题库 >

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

钮刚洁
2023-03-14
问题内容

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

我花了几天的时间试图解决这个问题,但无济于事。但是今天,我在python网站上找到了一个线程,在MySQL上找到了一个线程,在Lua用户上找到了一个线程,尽管没有任何解决方案,但有人说这种chcp 65001中断是固有的,但是这个突然退出引发了一些问题。

一劳永逸地知道此问题是否与chcp-design相关,或者有可能的解决方法,这将是很好的。

重现错误

chcp 65001

Python 3.X:

Python外壳

print('ä')

结果:它只是退出外壳

但是 ,这可行python.exe -c "print('ä')" ,也可行:print('\u00e4')

结果:ä

在Luajit2.0.4

print('ä')

结果:它只是退出外壳

但这有效: print('\xc3\xa4')

到目前为止,我已经提出了以下观察结果:

  1. 在命令提示符下直接输出有效。
  2. 基于Unicode的基于十六进制的字符等效。

所以, 这不是一个Python的错误
我们不能在Windows上使用Unicode字符直接在命令行程序命令提示符或任何其包装像Conemu,Cmder的(我使用Cmder能够看到和在Windows中使用Unicode字符外壳,而我这样做没有任何问题)。这个对吗?


问题答案:

要在Windows控制台中使用Python
2.7和3.x(3.6之前)的Unicode,请安装并启用win_unicode_console。像其他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来解决此错误。



 类似资料:
  • 你好团队, 我正在我的系统上运行一个Maven构建(mvn clean install),Maven构建在下面的代码行之后被终止,没有任何错误。 我使用的是最新的maven版本3.6.3(硬件配置-英特尔i5第4代处理器和16 GB RAM)。 下面是我用来执行项目maven构建的命令。 在IntelliJ中: D:\Software\jdk-11.0.10 9\bin\java。exe-Dmav

  • 我正在使用ApachePOI读取Excel文件,它在本地机器(独立程序)中运行良好,但在服务器(IBMWebSphere)中未运行。当遇到实例化工作簿时,它停止工作。 下面的罐子被使用。 commons-codec-1.5.jarpoi-3.9.jarpoi-examples-3.9.jarpoi-ooxml-3.9.jarpoi-ooxml-schemas-3.9.jarxmlbeans-2.6

  • 关于stack的第一个问题, 我正在windows 2003 server AMD Opteron 2.30 Ghz上运行cf10 Enterprise,内存为4gb。Im使用cfindex action=更新索引超过1k PDF 我得到了jvm内存错误和页面被杀死时,它作为一个预定的任务在凌晨运行。 这是页面中的代码: cfindex集合="pdfs"操作="更新"类型="路径"扩展名=". p

  • 如何修复致命错误jvmti.h没有这样的文件或目录编译终止的c代码Ubuntu?我的c代码是: JNIEXPORT void JNICALL Agent_OnUnload(JavaVM*vm){} 在终端中键入以下命令:gcc-wall-w-werror first_agent.c-o firstagent first_agent.c:1:19:致命错误:jvmti.h:没有终止此类文件或目录编译

  • 问题内容: 我在运行Jellybean(4.1-4.3)的设备中遇到HttpUrlConnection的一些问题,其中连接未关闭,并且执行多次后导致SocketException“打开的文件过多”。 我确实调用了HttpUrlConnection.disconnect()并在finally块中关闭了所有Inputstream,Outputstream,Reader和Writers。 转到adb s

  • 问题内容: 我找到了终止(关闭或停止)Java程序的方法。我找到了两个解决方案。 使用 return; 当我想退出或终止程序执行时,添加它。 使用 System.exit() ; 有时我用它。我从This Question中了解了 Sytem.exit()。 所以,我对他们都了解一点。但是我仍然对它们的实际工作方式感到困惑。请检查以下代码… 我确定 2不会出现。我想知道为什么或其他代码可以在的语句