以下代码在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é但是,在Python2.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')来修复此错误,但如果这样做,Python3中的输出将更改为:
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 气馁读到的。
处理这个问题的最佳方法是什么?
发布于 2017-01-09 07:54:15
首先,我们假设您希望支持Python2.7和3.5版本(2.6和3.0到3.2的处理方式略有不同)。
正如您已经阅读过的,setdefaultencoding是不鼓励的,实际上在您的情况下不需要。
要编写处理unicode文本的跨平台代码,通常只需要在几个地方指定字符串编码:
# -*- coding: utf-8 -*- (只有在代码中有带有unicode文本的字符串)下面是我如何通过遵循这些规则来更改您的示例:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
people = ['Nicholas Gyeney', 'André']
writers = ", ".join(people)
print(writers)
print("Writers: {}".format(writers))
print(type(writers))
print(len(writers))其中产出:
<type 'str'>
23以下是改变的地方:
\xe9替换为实际的Unicode字符(é)u前缀它在Python2.7.12和3.5.2中运行得很好。
但是请注意,删除u前缀将使python使用常规的str类型而不是unicode (参见print(type(writers))的输出)。对于utf-8,它在大多数地方都像一个unicode字符串一样工作,但是在检查文本长度时会返回一个错误的值。在本例中,len返回23,其中实际字符数为22。这是因为底层类型是str,它将每个字节算作一个字符,但是字符é实际上应该是两个字节。
换句话说,当输出数据很好时(如您的示例中所示),这是有效的,但如果您想对文本执行字符串操作,则不能这样做。在这种情况下,在字符串操作之前,仍然需要使用u前缀或将数据过度转换为unicode类型。
因此,如果不是简单的示例,最好还是继续使用u前缀。你需要在两个地方:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
people = [u'Nicholas Gyeney', u'André']
writers = ", ".join(people)
print(writers)
print(u"Writers: {}".format(writers))
print(type(writers))
print(len(writers))其中产出:
<type 'unicode'>
22注意:为了实现向后兼容性,在Python3.0中删除了u前缀,然后在Python3.3中再次引入了该前缀。
有关使用Python2中的unicode文本的所有复杂问题的详细说明,可在正式文档:Python2- Unicode方法中找到。
以下是指定文件编码的特殊注释的摘录:
Python支持在任何编码中编写Unicode文本,但您必须声明所使用的编码。这是通过将一个特殊的注释作为源文件的第一行或第二行来实现的: #!/usr/bin/env python #-*编码:拉丁-1 -*- u=u‘’abcdé‘打印ord(u-1) 该语法受Emacs用于指定文件局部变量的表示法启发。Emacs支持许多不同的变量,但是Python只支持
coding。-*-符号向Emacs表示注释是特殊的;它们对Python没有意义,而是一种惯例。Python在注释中查找coding: name或coding=name。 如果不包括这样的注释,默认的编码将是ASCII。
如果你掌握了"学习Python,第5版“一书,我鼓励你阅读第八部分"Unicode和Byte”第37章“高级主题”。它包含了在两代Python中使用Unicode文本的详细说明。
另一个值得注意的细节是,format总是返回一个ascii字符串,如果格式字符串是ascii,不管参数是unicode。
与此相反,如果任何参数为%,则使用unicode的旧样式格式将返回一个unicode字符串。所以不要写这个
print(u"Writers: {}".format(writers))您可以编写它,它不仅更短、更漂亮,而且可以在Python 2和3中使用:
print("Writers: %s" % writers)发布于 2017-01-09 07:06:25
您可以在格式化时提供Unicode前缀:
print(u"Writers: {}".format(writers))这确实解决了这个问题,但是,您正在用不必要的u''前缀乱扔Python3脚本。
您也可以在检查版本后使用from __future__ import unicode_literals,但我不会这样做,使用它通常比较困难,并且由于u''前缀充分发挥了作用,因此被认为是不推荐的。
发布于 2017-01-09 07:11:14
在Python2中,您应该为join和print使用unicode字符串。
people = [u'Nicholas Gyeney', u'Andr\xe9']
writers = u", ".join(people)
print(writers)
print(u"Writers: {}".format(writers))https://stackoverflow.com/questions/41542613
复制相似问题