我在Windows上使用Python 3.6。当我使用标准Windows Shell(cmd.exe)运行脚本时,stdin / stdout的默认文本编码为'utf-8',如Python 3.x所期望的那样:

python -c "import sys; print(sys.stdout.encoding)"
utf-8


但是,在IDLE shell上使用相同的命令会导致结果不同,这显然很烦人,特别是对于使用IDLE作为第一步IDE的初学者而言

>>> import sys; print(sys.stdout.encoding)
cp1252


碰巧IDLE定义了PseudoOutputFilePseudoInputFile类来包装stdout / stdin。这些类包括一个隐藏的_encoding属性,可用于根据需要切换编码

>>> sys.stdout._encoding = 'utf-8'
>>> print(sys.stdout.encoding)
utf-8


但是,每次启动脚本时都会取消此设置,因为IDLE在运行模块时会重新启动其外壳。是否有任何长期解决方案可以更改IDLE的stdin / stdout默认编码?

最佳答案

对于2.7、3.5,显示的命令行对我来说是cp437的响应-IBM PC或DOS编码。 Windows控制台的输出仅限于基本多语言平面(BMP)Unicode字符的子集。

对于3.6,Python的Windows控制台处理得到了显着改进,以使用utf-8,并可能打印任何unicode字符,具体取决于字体的可用性。

对于所有当前版本,IDLE也会为我报告cp1252(拉丁语1)。由于尝试获取系统编码,因此我不知道为什么会有所不同。但这几乎没有什么区别,因为它是虚拟或伪造的值。对我而言,非拉丁字符不能用latin1编码是一种欺骗,而所有BMP字符都可以用IDLE打印。所以我考虑过更换。

当将(unicode)字符串写入sys.stdout(通常与print一起使用)时,该字符串对象将在用户进程中被腌制为字节,通过套接字(实现细节可能会更改)发送到IDLE进程,然后被非腌制回字符串对象。效果就好像是使用非损耗utf编码之一对字符串进行了编码和解码。 UTF-32可能与酸洗最接近。

IDLE进程调用tkinter text.insert(index,string),它要求tk在小部件中插入字符串。但这仅适用于BMP字符。最终效果就好像输出编码是ucs-2,尽管我相信tk在内部使用了截断的utf-8。

同样,您在外壳程序或编辑器中输入的任何BMP字符在显示后都可以发送给用户进程stdin。

无论如何,更改pseudofile.encoding无效,这就是为什么issue 9290补丁的此部分将其设置为只读的原因

-        self.encoding = encoding
+        self._encoding = encoding
+
+    @property
+    def encoding(self):
+        return self._encoding


最初的下划线表示_encoding是私有(不隐藏)的实现细节,用户应忽略它。

10-08 03:11