Python中的Stdout编码

14

我是否有充分的理由不应该用这种方式开始所有我的Python程序呢?这样做是否会丢失一些特殊的东西?

#!/usr/bin/python
import os, sys
if sys.stdout.encoding == None:
    os.putenv("PYTHONIOENCODING",'UTF-8')
    os.execv(sys.executable,['python']+sys.argv)
print sys.stdout.encoding

60个问题与PYTHONIOENCODING相关,所以我猜这是一个常见的问题,但以防万一你不知道,这是因为当sys.stdout.encoding == None时只能打印ASCII字符,所以例如print "åäö"将抛出异常。

编辑 当stdout是管道时,会发生这种情况;python encoding.py | cat 将设置编码为None

另一个解决方案是更改stdout的编解码器sys.stdout = codecs.getwriter('utf8')(sys.stdout) 我猜这是正确的答案,尽管在该问题的评论中并非如此。


另请参见https://dev59.com/B3M_5IYBdhLWcg3wNwUv。 - Michael
3
在这些情况下,stdout是什么?一个管道吗?你怎么知道管道连接的任何内容都支持UTF8?在这种情况下,管道的设置工作是指定PYTHONIOENCODING的工作。 - Martijn Pieters
3
问题在于ASCII并非一个合理的默认选项。我同意,如果有人真的想要Latin-1或UTF-16,他们可以设置该环境变量,但作为默认值,UTF-8更好。 - Erik Johansson
Ubuntu在普通终端上正确设置了sys.stdout的编码,所以你这里没有说清楚的地方。 - Lennart Regebro
如果您的stdout是一个管道,这种情况会发生。 - Erik Johansson
显示剩余2条评论
1个回答

8

是的,有一个很好的理由不要像那样启动所有的Python程序。

首先:

如果Python不知道stdout支持什么编码,sys.stdout.encoding将为None。在大多数情况下,这是因为它根本不支持任何编码。在您的情况下,这是因为stdout是一个文件,而不是终端。但是它也可能设置为None,因为Python无法检测到终端的编码。

其次:您设置环境变量,然后再次使用相同的命令启动新进程。这非常丑陋。

因此,除非您打算是唯一使用程序的人,否则不应该像那样启动它们。但是,如果您计划成为唯一使用程序的人,则可以继续。

更深入的解释

在Python 2下更好的通用解决方案是将stdout视为它所代表的内容:一个8位接口。这意味着您打印到stdout的任何内容都应该是8位的。当您尝试打印Unicode数据时会出现错误,因为print将尝试将Unicode数据编码为stdout的编码,如果它是None,则假定为ASCII并失败,除非您设置了PYTHONIOENCODING。

但通过打印编码数据,您就不会遇到这个问题。即使输出被管道化,以下内容也可以完美运行:

print u'ÅÄÖ'.encode('UTF8')

然而,在 Python 3 中,这将失败。因为在 Python 3 中,stdout 不再是8位IO,你应该给它 Unicode 数据,它将自行编码。如果你给它二进制数据,它将打印表示形式。因此,在 Python 3 中,你首先就不会遇到这个问题。


为什么这是个坏主意,你没有真正提到...从程序中得不到任何数据比以错误的编码得到更糟吗?我的问题是这将由大约20人运行,我需要告诉他们都设置PYTHONIOENCODING,所以这是一个合理的默认值。 - Erik Johansson
@ErikJohansson:用错误的编码获取它会更糟。否则,您会收到一个错误,您可以修复它。您没有理由需要设置PYTHONIOENCODING,错误可能在其他地方。 - Lennart Regebro
还请参见上面链接的问题,我在p3k中尝试了这个方法,它似乎使用我的本地编码作为默认编码。 - Erik Johansson
@ErikJohansson:听起来这些是专门为您的环境制作的自定义脚本。如果是这样,那么就像我在答案中提到的那样,将其设置为UTF-8是可以的。但对于通用的开源脚本来说,这样做并不明智。将其设置为区域编码更加合理。您还可以查看sys.stdout.isatty()以检查它是否为终端。 - Lennart Regebro
是的,使用Python 3是个好主意,但是将它移植过去并不值得花费那么多精力。 - Erik Johansson
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接