以下代码适用于 Python 3:
people = [u'Nicholas Gyeney', u'Andr\xe9']
writers = ", ".join(people)
print(writers)
print("Writers: {}".format(writers))
并产生以下输出:
Nicholas Gyeney, André
Writers: Nicholas Gyeney, André
但是,在 Python 2.7 中,我收到以下错误:
Traceback (most recent call last):
File "python", line 4, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9'
in position 21: ordinal not in range(128)
我可以通过将 ", ".join(people)
更改为 ", ".join(people).encode('utf-8')
来修复此错误,但如果我这样做,Python 3 中的输出将更改为:
b'Nicholas Gyeney, Andr\xc3\xa9'
Writers: b'Nicholas Gyeney, Andr\xc3\xa9'
所以我尝试使用以下代码:
if sys.version_info < (3, 0):
reload(sys)
sys.setdefaultencoding('utf-8')
people = [u'Nicholas Gyeney', u'Andr\xe9']
writers = ", ".join(people)
print(writers)
print("Writers: {}".format(writers))
这使得我的代码适用于所有版本的 Python。但我读到 不鼓励 使用 setdefaultencoding
。
处理此问题的最佳方法是什么?
原文由 B Faley 发布,翻译遵循 CC BY-SA 4.0 许可协议
首先我们假设你想要支持 Python 2.7 和 3.5 版本(2.6 和 3.0 到 3.2 的处理方式有点不同)。
正如您已经阅读的那样,
setdefaultencoding
是不鼓励的,在您的情况下实际上不需要。要编写处理 unicode 文本的跨平台代码,通常只需要在几个地方指定字符串编码:
# -*- coding: utf-8 -*-
(仅当你的代码中有带有 unicode 文本的字符串文字时)以下是我如何按照这些规则更改您的示例:
输出:
这是发生了什么变化:
\xe9
替换为实际的 Unicode 字符 (é
)u
前缀它在 Python 2.7.12 和 3.5.2 中工作得很好。
But be warned that removing the
u
prefixes will make python use regularstr
type instead ofunicode
(see output ofprint(type(writers))
).在utf-8
的情况下,它在大多数地方都像 unicode 字符串一样工作,但是在检查文本长度时将返回错误的值。在此示例len
返回23
,其中实际字符数为22
。这是因为底层类型是str
,它将每个字节计为一个字符,但字符é
实际上应该是两个字节。换句话说,这在输出数据正常时有效(如您的示例所示),但如果您想对文本进行字符串操作则无效。在这种情况下,在字符串操作之前,您仍然需要使用
u
前缀或将数据显式转换为 unicode 类型。因此,如果不是您的简单示例,最好仍然使用
u
前缀。你需要在两个地方:输出:
注意:
u
前缀在 Python 3.0 中被删除,然后在 Python 3.3 中再次引入以实现向后兼容性。官方文档中提供了有关在 Python 2 中使用 unicode 文本的所有复杂性的详细说明: Python 2 - Unicode HOWTO 。
以下是指定文件编码的特殊注释的摘录:
print(“Writers: %s” % writers)
”`