在Python中通过sys.stdout编写unicode字符串

Rei*_*ica 17 python unicode macos terminal stdout

假设一个人不能使用print(从而享受自动编码检测的好处).所以这让我们失望了sys.stdout.但是,如果不做任何明智的编码sys.stdout是如此愚蠢.

现在,您可以阅读Python维基页面PrintFails并尝试以下代码:

$ python -c 'import sys, codecs, locale; print str(sys.stdout.encoding); \
  sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout);
Run Code Online (Sandbox Code Playgroud)

然而,这也不起作用(至少在Mac上).太明白为什么:

>>> import locale
>>> locale.getpreferredencoding()
'mac-roman'
>>> sys.stdout.encoding
'UTF-8'
Run Code Online (Sandbox Code Playgroud)

(UTF-8是终端理解的).

所以将上面的代码更改为:

$ python -c 'import sys, codecs, locale; print str(sys.stdout.encoding); \
  sys.stdout = codecs.getwriter(sys.stdout.encoding)(sys.stdout);
Run Code Online (Sandbox Code Playgroud)

现在,unicode字符串被正确发送到sys.stdout终端上并在终端上正确打印(sys.stdout连接到终端).

这是编写unicode字符串的正确方法sys.stdout还是我应该做的其他事情?

编辑:有时 - 比如说,当输出到less- 时sys.stdout.encoding将是None.在这种情况下,上面的代码将失败.

Sér*_*gio 31

export PYTHONIOENCODING=utf-8
Run Code Online (Sandbox Code Playgroud)

将完成这项工作,但无法在python本身设置它...

我们可以做的是验证是否设置并告诉用户在调用脚本之前设置它:

if __name__ == '__main__':
    if (sys.stdout.encoding is None):
        print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
        exit(1)
Run Code Online (Sandbox Code Playgroud)


nos*_*klo 10

最好的办法是检查您是否直接连接到终端.如果是,请使用终端的编码.否则,请使用系统首选编码.

if sys.stdout.isatty():
    default_encoding = sys.stdout.encoding
else:
    default_encoding = locale.getpreferredencoding()
Run Code Online (Sandbox Code Playgroud)

始终允许用户指定她想要的编码也非常重要.通常我将它作为命令行选项(如-e ENCODING),并用optparse模块解析它.

另一个好处是不要sys.stdout用自动编码器覆盖.创建编码器并使用它,但不要sys.stdout管它.您可以导入直接编写编码字节串的第三方库sys.stdout.


dav*_*agp 8

存在可选的环境变量"PYTHONIOENCODING",其可以被设置为期望的默认编码.这将是以与所有Python一致的方式获取用户期望的编码的一种方式.它被埋葬在Python手册这里.


elc*_*uco 6

这就是我在我的应用程序中所做的事情:

sys.stdout.write(s.encode('utf-8'))

这是从argv读取UTF-8名称的完全相反的修复:

for file in sys.argv[1:]:
    file = file.decode('utf-8')
Run Code Online (Sandbox Code Playgroud)

这是非常难看的(恕我直言),因为它迫使你使用UTF-8 ..这是Linux/Mac上的常态,但不是在Windows上......无论如何都适合我:)


Mar*_*wis 3

我不清楚为什么你不能打印;但假设是这样,是的,这种方法对我来说看起来是正确的。

  • 如果输出到管道,它不可能知道要使用什么编码(因为它不知道 less(1) 在管道的另一端)。因此,您的应用程序必须自行确定/决定编码。 (5认同)
  • 您可以构建完整的线条,然后打印它们。 (3认同)