如何以与python2和python3一起使用的方式将utf8写入标准输出

时间:2014-05-30 00:00:19

标签: python python-3.x encoding stdout

我想写一个非ascii字符,让我们说到标准输出。棘手的部分似乎是我想要连接到该字符串的一些数据是从json读取的。考虑以下简单的json文档:

{"foo":"bar"}

我加入了这个,因为如果我只想打印,那么只需写下来就足够了:

print("→")

它将在python2和python3中做正确的事。

所以我想打印foo和我的非ascii字符的值。我发现这样做的唯一方法就是它在python2和python3中都有效:

getattr(sys.stdout, 'buffer', sys.stdout).write(data["foo"].encode("utf8")+u"→".encode("utf8"))

getattr(sys.stdout, 'buffer', sys.stdout).write((data["foo"]+u"→").encode("utf8"))

重要的是不要错过u前面的,否则python2会抛出UnicodeDecodeError

使用print这样的函数:

print((data["foo"]+u"→").encode("utf8"), file=(getattr(sys.stdout, 'buffer', sys.stdout)))

似乎没有用,因为python3会抱怨TypeError: 'str' does not support the buffer interface

我找到了最好的方法还是有更好的选择?我可以使打印功能起作用吗?

2 个答案:

答案 0 :(得分:3)

我能想到的最简洁的是以下内容,您可以通过一些便利功能(甚至替换/覆盖打印功能)使其更加简洁:

# -*- coding=utf-8 -*-
import codecs
import os
import sys

# if you include the -*- coding line, you can use this
output = 'bar' + u'→'
# otherwise, use this
output = 'bar' + b'\xe2\x86\x92'.decode('utf-8')

if sys.stdout.encoding == 'UTF-8':
    print(output)
else:
    output += os.linesep
    if sys.version_info[0] >= 3:
        sys.stdout.buffer.write(bytes(output.encode('utf-8')))
    else:
        codecs.getwriter('utf-8')(sys.stdout).write(output)

最好的选择是使用 - * - 编码行,它允许您使用文件中的实际字符。但是如果出于某种原因,你不能使用编码行,那么没有它就可以完成。

这个(有和没有编码行)在Linux(Arch)上使用python 2.7.7和3.4.1。 如果终端的编码不是UTF-8,它也可以工作。 (在Arch Linux上,我只是使用不同的LANG环境变量来更改编码。)

LANG=zh_CN python test.py

在Windows上运行,我尝试使用2.6,2.7,3.3和3.4。通过排序,我的意思是我可以让'→'字符只显示在一个薄薄的终端上。在cmd终端上,该字符将显示为'ΓåÆ'。 (那里可能有一些简单的东西。)

答案 1 :(得分:1)

如果您不需要打印到sys.stdout.buffer,则以下内容应该打印到sys.stdout。我在Python 2.7和3.4中都尝试过它,它似乎运行良好:

# -*- coding=utf-8 -*-
print("bar" + u"→")