为什么Python程序在Windows系统中标准输出和重定向到文件后的输出结果不一样?

p.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, locale print(sys.stdout.encoding, sys.getdefaultencoding(), locale.getpreferredencoding()) print(‘你好,世界’)

python 版本 3.6.3,中文 Windows 7 系统,cmd 下执行以下命令

C:\Users\>python p.py
utf-8 utf-8 cp936
你好,世界

C:\Users>python p.py > p.txt

p.txt 编码为 ANSI,内容为

cp936 utf-8 cp936
你好,世界

sys.stdout.encoding的结果不同,为什么呢?


为什么Python程序在Windows系统中标准输出和重定向到文件后的输出结果不一样?

6 回复

我觉得 help(sys.stdout),然后再看看这篇文章<https://github.com/tartley/colorama/issues/125>或许对你有帮助。


这个问题通常是因为控制台和文件对编码的处理方式不同。在Windows的cmd或PowerShell里,Python默认会用当前控制台的编码(比如gbk)来编码输出文本。但当你重定向到文件时,Python可能会用不同的默认编码(比如UTF-8),或者文件本身没有正确声明编码,导致显示乱码。

举个例子,如果你的脚本里有非ASCII字符(比如中文),直接打印到控制台可能正常,但重定向到文件后打开可能就是乱码。这是因为控制台能自动匹配编码,而文本编辑器可能用另一种编码打开文件。

解决方法是明确指定编码。可以在脚本里设置环境变量PYTHONIOENCODING,或者在代码里对标准输出做包装。更直接的办法是在重定向时让系统用UTF-8:在PowerShell里可以用chcp 65001切换代码页,或者用python script.py > output.txt -X utf8(Python 3.7+支持-X utf8选项)。

简单说,就是统一用UTF-8编码能避免这类问题。

这样说明是不是很容易理解?

import sys, locale
fh = open(“f.txt”, “w”, encoding=“utf-8”) # 换成"gbk", "big5"等其它编码试试
sys.stdout = fh
print(sys.stdout.encoding, sys.getdefaultencoding(), locale.getpreferredencoding())
print(‘你好,世界’)
fh.close()

因为打开一个文件默认是用 preferred encoding indicated by locale,而 console 是 UTF-8。

应该和 isatty() 有关。
sys.stdout.isatty()在直接执行的情况下返回 True,如果输出重定向到文件则返回 False。
文档中找到了相应的解释

The character encoding is platform-dependent. Under Windows, if the stream is interactive (that is, if its isatty() method returns True), the console codepage is used, otherwise the ANSI code page. Under other platforms, the locale encoding is used (see locale.getpreferredencoding()).

可能就如这篇文章中说的一样
http://blog.csdn.net/haiross/article/details/36189103
<br>if sys.stdout.isatty():<br> default_encoding = sys.stdout.encoding<br>else:<br> default_encoding = locale.getpreferredencoding()<br>
但是我还不清楚如何去源代码中具体查看。

可是文档里说if the stream is interactive (that is, if its isatty() method returns True), the console codepage is used, otherwise the ANSI code page
chcp 执行后显示代码页为 936,为什么 sys.stdout.encoding 会是 utf-8 呢?

回到顶部