小编典典

为什么脚本语言不将Unicode输出到Windows控制台?

python

Windows控制台至少在十年之前就可以识别Unicode,甚至可以追溯到Windows
NT。但是由于某种原因,包括Perl和Python在内的主要跨平台脚本语言仅输出各种8位编码,因此需要很多麻烦来解决。Perl发出“正在打印宽字符”警告,Python给出一个charmap错误并退出。为什么这些年来,他们为什么不只是简单地调用输出UTF-16
Unicode的Win32 -W API,而不是通过ANSI /代码页瓶颈强制执行所有操作?

只是跨平台性能的优先级低吗?语言是否在内部使用UTF-8并觉得太麻烦而无法输出UTF-16?还是-W API本质上被破坏到不能按原样使用的程度?

更新

似乎所有各方都应对此负责。我以为脚本语言可以只wprintf在Windows上调用,而让OS
/运行时担心诸如重定向之类的问题。但是事实证明,即使是Windows上的wprintf也可以将宽字符转换为ANSI,然后再打印回控制台

请让我知道是否已解决,因为错误报告链接似乎已损坏,但wprintf的Visual C测试代码仍然失败,而WriteConsoleW的代码却成功了。

更新2

实际上,您可以使用C将UTF-16打印到控制台,wprintf但前提是您必须先这样做_setmode(_fileno(stdout), _O_U16TEXT)

在C中,您可以将UTF-8打印到其代码页设置为65001的控制台,但是Perl,Python,PHP和Ruby都有一些错误可以阻止这种情况。Perl和PHP通过在包含至少一个宽字符的行之后添加其他空行来破坏输出。Ruby的腐败输出略有不同。Python崩溃。

更新3

Node.js是开箱即用的第一种没有此问题的脚本语言。

2007年底首次报告以来
Python开发人员团队逐渐意识到这是一个真正的问题并且在2016年进行了大量的活动来充分理解并完全修复该错误。


阅读 175

收藏
2020-12-20

共1个答案

小编典典

主要问题似乎在于,不可能仅在使用标准C库且没有平台相关或第三方扩展的Windows上使用Unicode。您提到的语言源自Unix平台,该平台的Unicode实现方法与C很好地融合在一起(它们使用普通的char*字符串,C语言环境功能和UTF-8)。如果要在C语言中执行Unicode,则或多或少必须编写两次所有内容:一次使用非标准的Microsoft扩展,一次使用所有其他操作系统的标准C
API函数。尽管可以做到这一点,但它通常没有很高的优先级,因为它很麻烦,而且大多数脚本语言开发人员还是讨厌或忽略Windows。

从更高的技术层面来看,我认为大多数标准库设计人员所做的基本假设是,所有I /
O流本质上都基于操作系统级别的字节,这适用于所有操作系统上的文件以及Unix上的所有流。类系统,唯一例外是Windows控制台。因此,如果要合并Windows控制台I
/ O,则必须在很大程度上修改许多类库和编程语言标准的体系结构。

另一个比较主观的观点是,微软只是不足以促进Unicode的使用。第一个具有不错的(当时)的Unicode支持的Windows操作系统是Windows NT
3.1,该版本于1993年发布,远远早于Linux和OS
X增强了对Unicode的支持。尽管如此,在这些操作系统中向Unicode的过渡更加无缝和毫无问题。微软再次听取了销售人员的意见,而不是工程师的意见,直到2001年,技术上已经过时的Windows
9x一直保留到现在。他们并没有强迫开发人员使用干净的Unicode接口,而是提供了已损坏的,现在不需要的8位API接口,并邀请程序员使用它(请参阅有关Stack
Overflow的一些近期Windows API问题,大多数新手 仍然 使用可怕的旧版API!)。

Unicode发行时,许多人意识到它是有用的。Unicode开始时是纯16位编码,因此使用16位代码单元是很自然的。微软然后显然说:“好,我们有16位编码,所以我们必须创建16位API”,但没有意识到没有人会使用它。但是,Unix专家认为:“我们如何以一种高效且向后兼容的方式将其集成到当前系统中,以便人们真正使用它?”
随后发明了UTF-8,这是一项出色的工程。就像创建Unix时一样,Unix人们认为更多,需要更长的时间,财务上的成功较少,但最终做到了。

我无法评论Perl(但我认为Perl社区中的Windows仇恨者多于Python社区),但是关于Python,我知道BDFL(也不太喜欢Windows)已经声明了足够的Unicode支持在所有平台上都是一个主要目标。

2020-12-20