将python输出重定向到文件会在Windows

时间:2018-12-31 05:08:33

标签: python windows encoding

我正在尝试将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中修复吗?

2 个答案:

答案 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(不是字符串),因此需要编码参数。

编码(用于将字符串转换为字节)因平台而异:

  • 在 Linux 和 macOS 上,它来自当前语言环境;
  • 在 Windows 上使用的是“非 Unicode 程序的当前语言”(在命令行窗口中设置的代码页无关紧要)。

(感谢@Eric Leung 提供精确链接)

后续问题是为什么 Windows 上的 Python 对非 Unicode 程序使用当前系统区域设置,而不是 chcp 命令设置的内容,但我会将其留给其他人。

还需要提及的是,Windows 10 的区域设置中有一个名为“Beta:使用 Unicode UTF-8...”的复选框(要打开 - Win+R,请键入 intl.cpl)。通过选中复选框,上面的示例可以正常工作。但是默认情况下此复选框处于关闭状态,并且非常深入系统设置。