当输送Python程序的输出时,Python解释器会混淆编码并将其设置为None。这意味着这样一个程序:

# -*- coding: utf-8 -*-
print u"åäö"

正常运行时工作正常,但失败:

unicode编码错误:'ascii'编解码器无法编码字符u'\xa0'在位置0:序数不在范围(128)

在管道序列中使用时。

什么是最好的方法使这工作时管道?我能告诉它使用shell/文件系统/任何正在使用的编码吗?

到目前为止,我看到的建议是直接修改你的site.py,或者使用以下方法硬编码defaultencoding:

# -*- coding: utf-8 -*-
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
print u"åäö"

有没有更好的方法让管道工作?


当前回答

您的代码在脚本中运行时可以工作,因为Python将输出编码为终端应用程序使用的任何编码。如果你是管道,你必须自己编码。

一条经验法则是:始终在内部使用Unicode。解码你收到的,编码你发送的。

# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')

另一个有教育意义的例子是一个在ISO-8859-1和UTF-8之间转换的Python程序,在两者之间使用大写字母。

import sys
for line in sys.stdin:
    # Decode what you receive:
    line = line.decode('iso8859-1')

    # Work with Unicode internally:
    line = line.upper()

    # Encode what you send:
    line = line.encode('utf-8')
    sys.stdout.write(line)

设置系统默认编码是一个坏主意,因为您使用的一些模块和库可能依赖于它是ASCII的事实。不要这样做。

其他回答

我很惊讶这个答案还没有被贴在这里

从Python 3.7开始,你可以用reconfigure()改变标准流的编码: sys.stdout.reconfigure(编码=“utf - 8”) 还可以通过添加errors参数来修改处理编码错误的方式。

https://stackoverflow.com/a/52372390/15675011

您的代码在脚本中运行时可以工作,因为Python将输出编码为终端应用程序使用的任何编码。如果你是管道,你必须自己编码。

一条经验法则是:始终在内部使用Unicode。解码你收到的,编码你发送的。

# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')

另一个有教育意义的例子是一个在ISO-8859-1和UTF-8之间转换的Python程序,在两者之间使用大写字母。

import sys
for line in sys.stdin:
    # Decode what you receive:
    line = line.decode('iso8859-1')

    # Work with Unicode internally:
    line = line.upper()

    # Encode what you send:
    line = line.encode('utf-8')
    sys.stdout.write(line)

设置系统默认编码是一个坏主意,因为您使用的一些模块和库可能依赖于它是ASCII的事实。不要这样做。

克雷格·麦昆(Craig McQueen)的答案有争议的净化版。

import sys, codecs
class EncodedOut:
    def __init__(self, enc):
        self.enc = enc
        self.stdout = sys.stdout
    def __enter__(self):
        if sys.stdout.encoding is None:
            w = codecs.getwriter(self.enc)
            sys.stdout = w(sys.stdout)
    def __exit__(self, exc_ty, exc_val, tb):
        sys.stdout = self.stdout

用法:

with EncodedOut('utf-8'):
    print u'ÅÄÖåäö'

我在一个遗留应用程序中遇到了这个问题,并且很难确定在哪里打印了内容。我用这个方法帮助自己:

# encoding_utf8.py
import codecs
import builtins


def print_utf8(text, **kwargs):
    print(str(text).encode('utf-8'), **kwargs)


def print_utf8(fn):
    def print_fn(*args, **kwargs):
        return fn(str(*args).encode('utf-8'), **kwargs)
    return print_fn


builtins.print = print_utf8(print)

在我的脚本顶部,test.py:

import encoding_utf8
string = 'Axwell Λ Ingrosso'
print(string)

注意,这改变了所有调用打印使用编码,所以你的控制台将打印这个:

$ python test.py
b'Axwell \xce\x9b Ingrosso'

首先,关于这个解决方案:

# -*- coding: utf-8 -*-
print u"åäö".encode('utf-8')

每次都显式地用给定的编码打印是不实际的。这将是重复的,而且容易出错。

一个更好的解决方案是改变sys。在程序开始时使用标准输出,以使用选定的编码进行编码。这是我在Python上找到的一个解决方案:如何选择sys.stdout.encoding ?,特别是“toka”的评论:

import sys
import codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)