当输送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 3.7开始,我们可以使用Python UTF-8模式,通过使用命令行选项-X utf8:

 python -X utf8 testzh.py

脚本testzh.py包含

print("Content-type: text/html; charset=UTF-8\n") 
print("地球你好!")

将Windows 10 Internet Service IIS设置为CGI脚本处理程序

我们将Executable设置为:

"C:\Program Files\Python39\python.exe" -X utf8 %s

这适用于微软浏览器上的中文表意文字。像这样的截图:否则,错误发生。

请参阅https://docs.python.org/3/library/os.html#utf8-mode

其他回答

export PYTHONIOENCODING=utf-8

完成工作,但不能设置在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)

更新以回复评论: 问题只存在于管道到标准输出时。 我在Fedora 25 Python 2.7.13中测试

python --version
Python 2.7.13

猫b.py

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import sys

print sys.stdout.encoding

运行。/ b.py

UTF-8

运行。/b.p y| less

None

上周我也遇到了类似的问题。在我的IDE (PyCharm)中很容易修复。

以下是我的解决方案:

从PyCharm菜单栏开始:File -> Settings…->编辑器->文件编码,然后设置:“IDE编码”,“项目编码”和“属性文件的默认编码”全部为UTF-8,她现在的工作就像一个魅力。

希望这能有所帮助!

您的代码在脚本中运行时可以工作,因为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的事实。不要这样做。

您可能想尝试将环境变量“PYTHONIOENCODING”更改为“utf_8”。我写了一页关于我在这个问题上的痛苦经历。

博客文章的Tl;dr:

import sys, locale, os
print(sys.stdout.encoding)
print(sys.stdout.isatty())
print(locale.getpreferredencoding())
print(sys.getfilesystemencoding())
print(os.environ["PYTHONIOENCODING"])
print(chr(246), chr(9786), chr(9787))

给你

utf_8
False
ANSI_X3.4-1968
ascii
utf_8
ö ☺ ☻

克雷格·麦昆(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'ÅÄÖåäö'