14

为什么我不应该用这个来启动我的所有python 程序,有充分的理由吗?像这样执行 exec 时有什么特别的丢失吗?

#!/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

关于 PYTHONIOENCODING有60 个问题,所以我想这是一个常见问题,但如果你不知道,这样做是因为sys.stdout.encoding == None那时你只能打印 ascii 字符,所以 egprint "åäö"会抛出异常..

编辑当 stdout 是管道时,这发生在我身上;python encoding.py|cat将编码设置为无

另一个解决方案是更改标准输出的编解码器, sys.stdout = codecs.getwriter('utf8')(sys.stdout)我猜这是正确的答案,尽管对该问题的评论。

4

1 回答 1

8

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

首先:

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

其次:您设置环境变量,然后再次使用 smae 命令启动一个新进程。那是相当丑陋的。

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

更深入的解释

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

但是通过打印编码数据,你就没有这个问题了。即使输出通过管道传输,以下内容也能完美运行:

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

(不过在 Python 3 下会失败,因为在 Python 3 下,stdout 不再是 8 位 IO,你应该给它 Unicode 数据,它会自己编码。如果你给它二进制数据,它会打印表示。因此,在 Python 3 上,你一开始就没有这个问题)。

于 2013-04-01T09:15:05.737 回答