我在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定义了
PseudoOutputFile
和PseudoInputFile
类来包装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是私有(不隐藏)的实现细节,用户应忽略它。