Python 2.7 再次出现 Unicode 混乱问题

3

我已经阅读了这篇文章:

在Python中管道传输stdout时设置正确的编码

我试图遵循以下原则:"始终在内部使用Unicode。解码接收到的内容,编码发送的内容。"

这是我的主文件:

# coding: utf-8

import os
import sys

from myplugin import MyPlugin
if __name__ == '__main__':
    c = MyPlugin()
    a = unicode(open('myfile.txt').read().decode('utf8'))
    print(c.generate(a).encode('utf8'))

我的困扰在于:
  • 我从utf8文件中读取数据并进行解码。
  • 然后,我将其强制转换为Unicode,即unicode(open('myfile.txt').read().decode('utf8'))
  • 接着,我尝试将其输出到终端上。
  • 在Linux终端上,我需要将其重新编码为utf8。因为这一直都是一个Unicode字符串,所以我认为这是正常的(如果我理解有误,请纠正我)
  • 当我在Windows的Pycharm下运行时,它被编码了两次utf8,导致出现像agréable, déjÃ这样的问题。因此,如果我删除encode('utf8')(将最后一行改为print(c.generate(a))),那么它可以在Pycharm中正常工作,但在Linux上就无法工作,会出现'ascii' codec can't encode character u'\xe9' in position之类的问题。

如果我在命令行中尝试:

  • Linux/shell ssh: import sys sys.stdout.encoding 我得到了'UTF-8'
  • Linux/shell 在我的代码中: import sys sys.stdout.encoding 我得到了None ,这是什么情况?
  • Windows/Pycharm: import sys sys.stdout.encoding 我得到了'windows-1252'

什么是使这在两个环境下正常工作的最佳方法?


我喜欢使用codecsutf-8格式打开文件,并且在代码中始终使用u"anystring"。当然,文件必须保存为utf-8格式。这样我就不会遇到太多问题了。如果你正在使用IDE,也必须将其配置为默认读取utf-8,同样适用于shell。这可能对你没有帮助,但这是我避免遇到太多编码问题的方法。 - colidyre
2个回答

0
unicode(open('myfile.txt').read().decode('utf8'))

不需要使用unicode进行包装,因为str.decode的结果已经是unicode了。

print(c.generate(a).encode('utf8'))

不需要进行编码,因为Python会根据终端编码自动对字符串进行编码。

因此,这是正确的做法。

print(c.generate(a))

你遇到了 'ascii' codec can't encode character u'\xe9' in position 的问题,因为你的 Linux 终端使用的是 ascii 编码,所以 Python 无法将 Unicode 字符打印到终端上。

请参考 https://wiki.python.org/moin/PrintFails

我建议你修复终端(环境),而不是代码。你不应该依赖于终端编码,特别是当你通常将这些信息打印到文件中时。

如果你仍然想要将其打印到任何支持 ASCII 的终端上,你可以使用 str.encode('unicode-escape')

>>> print(u'щхжы'.encode('unicode-escape'))
\u0449\u0445\u0436\u044b

但它对于人类而言不太易读,所以我看不出有什么意义。


你说我的终端有ASCII编码,但我不明白的是,如果我在终端中作为命令行启动Python,并尝试使用sys.stdout.encoding,我会得到“UTF-8”,而如果我使用“python mymain.py”启动它,则会得到“None”作为编码,这是为什么? - Olivier Pons
如果我在Python命令行中尝试您的示例,print u"\u03A9"可以正常工作,但在主文件中却不行。这个问题可能来自哪里? - Olivier Pons
好的,找到解决方法了:我的最后一行应该是 print(c.generate(a).encode(sys.stdout.encoding)) - Olivier Pons
此处所述,当Python无法检测到输出的所需字符集时,它会将sys.stdout.encoding设置为None,并且print将调用“ascii”编解码器。但我不知道在使用脚本的情况下为什么会出现这种情况。你是如何启动脚本的? - warvariuc
我会这样启动它: python myfile.py - Olivier Pons
显示剩余2条评论

0

你的理念是正确的,但你过于复杂化了问题,让你的代码变得脆弱。

在文本模式下打开文件,让它自动转换为Unicode。然后不要编码就可以直接输出 - print 函数应该可以自动确定正确的编码。

如果你的 Linux 环境没有设置正确,那么在你的 Linux 环境变量中设置 PYTHONIOENCODING=utf-8(使用 export PYTHONIOENCODING=utf-8)来修复 print 过程中出现的任何问题。你应该考虑将区域设置为 UTF-8 版本,例如 en_GB.UTF-8,以避免必须定义 PYTHONIOENCODING

PyCharm 应该可以直接使用,无需修改。

你的代码应该像这样:

import os
import sys
import io

from myplugin import MyPlugin

if __name__ == '__main__':
    c = MyPlugin()
    # t is the default
    with io.open('myfile.txt', 'rt', encoding='utf-8') as myfile:
        # a is now a Unicode string
        a = myfile.read()

    result = c.generate(a)
    print result

如果您正在使用Python 3.x,则从io.open()中删除import io和io.。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接