Mey*_*sam 5 python string utf-8 python-2.7 python-3.x
以下代码适用于Python 3:
people = [u'Nicholas Gyeney', u'Andr\xe9']
writers = ", ".join(people)
print(writers)
print("Writers: {}".format(writers))
Run Code Online (Sandbox Code Playgroud)
并产生以下输出:
Nicholas Gyeney, André
Writers: Nicholas Gyeney, André
Run Code Online (Sandbox Code Playgroud)
但是,在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)
Run Code Online (Sandbox Code Playgroud)
我可以通过更改", ".join(people)为修复此错误", ".join(people).encode('utf-8'),但如果我这样做,Python 3中的输出将更改为:
b'Nicholas Gyeney, Andr\xc3\xa9'
Writers: b'Nicholas Gyeney, Andr\xc3\xa9'
Run Code Online (Sandbox Code Playgroud)
所以我尝试使用以下代码:
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))
Run Code Online (Sandbox Code Playgroud)
这使我的代码适用于所有版本的Python.但我读到使用setdefaultencoding 是不鼓励的.
处理这个问题的最佳方法是什么?
首先,我们假设您要支持Python 2.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))
Run Code Online (Sandbox Code Playgroud)
哪个输出:
<type 'str'>
23
Run Code Online (Sandbox Code Playgroud)
这是改变了:
\xe9为实际的Unicode字符(é)u前缀它在Python 2.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))
Run Code Online (Sandbox Code Playgroud)
哪个输出:
<type 'unicode'>
22
Run Code Online (Sandbox Code Playgroud)
注意:u在Python 3.0中删除了前缀,然后在Python 3.3中再次重新引入,以实现向后兼容.
有关在Python 2中使用unicode文本的所有复杂性的详细说明,请参阅官方文档:Python 2 - Unicode HOWTO.
以下是指定文件编码的特殊注释的摘录:
Python支持在任何编码中编写Unicode文字,但您必须声明正在使用的编码.这是通过将特殊注释包含在源文件的第一行或第二行来完成的:
Run Code Online (Sandbox Code Playgroud)#!/usr/bin/env python # -*- coding: latin-1 -*- u = u'abcdé' print ord(u[-1])语法的灵感来自Emacs用于指定文件本地变量的表示法.Emacs支持许多不同的变量,但Python只支持
coding.这些-*-符号向Emacs表明评论是特殊的; 它们对Python没有意义,但却是一种惯例.Python 在注释中查找coding: name或coding=name在注释中查找.如果您不包含此类注释,则使用的默认编码为ASCII.
如果您掌握了" 学习Python,第5版 " 这本书,我建议您阅读第VIII部分中的第37章"Unicode和字节字符串".高级主题.它包含在两代Python中使用Unicode文本的详细说明.
值得一提的另一个细节是,如果格式字符串是,则format始终返回一个ascii字符串ascii,无论参数是什么unicode.
与此相反,旧样式格式化如果有任何参数则%返回一个unicode字符串unicode.所以不要写这个
print(u"Writers: {}".format(writers))
Run Code Online (Sandbox Code Playgroud)
你可以写这个,它不仅更短更漂亮,而且适用于Python 2和3:
print("Writers: %s" % writers)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12005 次 |
| 最近记录: |