我正在尝试将python脚本的输出重定向到文件。当输出包含非ASCII字符时,它可以在macOS和Linux上运行,但不能在Windows上运行。
我已经将问题推导出为一个简单的测试。以下是Windows命令提示符窗口中显示的内容。该测试仅是一次打印通话。
Microsoft Windows [Version 10.0.17134.472]
(c) 2018 Microsoft Corporation. All rights reserved.
D:\>set PY
PYTHONIOENCODING=utf-8
D:\>type pipetest.py
print('\u0422\u0435\u0441\u0442')
D:\>python pipetest.py
Тест
D:\>python pipetest.py > test.txt
D:\>type test.txt
Тест
D:\>type test.txt | iconv -f utf-8 -t utf-8
Тест
D:\>set PYTHONIOENCODING=
D:\>python pipetest.py
Тест
D:\>python pipetest.py > test.txt
Traceback (most recent call last):
File "pipetest.py", line 1, in <module>
print('\u0422\u0435\u0441\u0442')
File "C:\Python\Python37\lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-3: character maps to <undefined>
D:\>python -V
Python 3.7.2
可以看到设置PYTHONIOENCODING环境变量会有所帮助,但我不明白为什么需要设置它。当输出是终端时,它可以工作,但是如果输出是文件,则失败。为什么在stdout不是控制台的情况下使用cp1252?
也许这是一个错误,可以在Windows版本的python中修复吗?
答案 0 :(得分:2)
根据 Python 文档,Windows 版本在控制台设备 (utr-8) 和非字符设备(如磁盘文件和管道(系统区域设置))上使用不同的字符编码。 PYTHONIOENCODING 可用于覆盖它。
https://docs.python.org/3/library/sys.html#sys.stdout
另一种方法是直接在程序中更改编码,我试过了,效果很好。
sys.stdout.reconfigure(encoding='utf-8')
https://docs.python.org/3/library/io.html#io.TextIOWrapper.reconfigure
答案 1 :(得分:0)
Python 需要将二进制数据写入stdout
(不是字符串),因此需要编码参数。
编码(用于将字符串转换为字节)因平台而异:
(感谢@Eric Leung 提供精确链接)
后续问题是为什么 Windows 上的 Python 对非 Unicode 程序使用当前系统区域设置,而不是 chcp
命令设置的内容,但我会将其留给其他人。
还需要提及的是,Windows 10 的区域设置中有一个名为“Beta:使用 Unicode UTF-8...”的复选框(要打开 - Win+R,请键入 intl.cpl
)。通过选中复选框,上面的示例可以正常工作。但是默认情况下此复选框处于关闭状态,并且非常深入系统设置。