【问题标题】:Stdout encoding in pythonpython中的标准输出编码
【发布时间】:2013-03-22 08:06:51
【问题描述】:

我是否有充分的理由不应该用它来启动我的所有我的 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

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

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

另一种解决方案是更改 codec of stdout sys.stdout = codecs.getwriter('utf8')(sys.stdout),我猜这是正确的答案,尽管该问题的 cmets。

【问题讨论】:

  • 这是什么平台,顺便说一句?只是出于兴趣。
  • 在这些情况下,什么是 标准输出?管道?你怎么知道管道连接的任何东西都可以支持UTF8?在这种情况下,设置管道以指定 PYTHONIOENCODING 的工作就是。
  • 问题是 ASCII 不是一个健全的默认值,我同意如果有人真的想要 latin-1 或 UTF-16,他们可以设置那个 ENV 变量,但默认 UTF-8 很多更好
  • @LennartRegebro Ubuntu 12.04 python 2.7

标签: python unicode character-encoding


【解决方案1】:

是的,我们有充分的理由不这样启动所有 Python 程序。

首先:

sys.stdout.encoding 是 None 如果 Python 不知道标准输出支持什么编码。在大多数情况下,这是因为它根本不支持任何编码。在您的情况下,这是因为标准输出是一个文件,而不是终端。但它可以设置为 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 上,您一开始就没有这个问题。

【讨论】:

  • 为什么这是一个坏主意,你并没有真正提到......更糟糕的是没有从程序中获取任何数据,或者以错误的编码获取数据?我的问题是它由大约 20 人运行,我需要告诉他们所有人设置 PYTHONIOENCODING,所以这是一个合理的默认设置。
  • @ErikJohansson:使用错误的编码会更糟。否则你会得到一个可以修复的错误。您没有理由需要设置 PYTHONIOENCODING,错误在其他地方。
  • @Lennart_Regebro:不,虽然我同意 exec 是一个丑陋的解决方案,但默认为输出编码没有错。应用程序必须能够输出数据才能工作。
  • 另见上面链接的问题,我在 p3k 中试过这个,它似乎使用我的语言环境作为默认编码。
  • @ErikJohansson:在我看来,这些是专门为您的环境制作的自定义脚本。如果是这样,那么正如我在回答中提到的,将其设置为 UTF-8 就可以了。但对于通用的开源脚本,它不是。将其设置为区域设置编码更为明智。您还可以查看 sys.stdout.isatty() 来检查它是否是终端。
猜你喜欢
  • 2012-09-30
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-07
  • 1970-01-01
  • 2013-05-01
相关资源
最近更新 更多