您的位置:首页 > 其它

使用from __future__ import unicode_literals时要注意的问题

2015-05-01 19:16 483 查看
add by zhj: 在Python中有些库的接口要求参数必须是str类型字符串,有些接口要求参数必须是unicode类型字符串。对于str类型的字符串,调用len()和遍历时,其实都是以字节为单位的,这个太坑爹了,同一个字符使用不同的编码格式,长度往往是不同的。对unicode类型的字符串调用len()和遍历才是以字符为单位,这是我们所要的。另外,Django,Django REST framework的接口都是返回unicode类型的字符串。为了统一,我个人建议使用from __future__ import unicode_literals,将模块中显式出现的所有字符串转为unicode类型,不过,对于必须使用str字符串的地方要加以注意。关于字符串类型,也是Python2坑爹的地方

在py2.7的项目中用了__future__模块中的 unicode_literals 来为兼容py3.x做准备,今天遇到一个UnicodeEncodeError的错误,跟了下,发现这个小坑值得注意。是怎么样的一个坑呢?跟着代码看看。顺便深究一下原理。

1. 问题

未引用unicode_literals

#coding:utf-8
from datetime import datetime

now = datetime.now()
print now.strftime('%m月%d日 %H:%M')


这段代码正常执行,输出: 03月12日 21:53

引入unicode_literals

#coding:utf-8
from __future__ import unicode_literals
from datetime import datetime

now = datetime.now()
print now.strftime('%m月%d日 %H:%M')


抛出如下错误:

Traceback (most recent call last):
File "unicode_error_demo2.py", line 7, in <module>
print now.strftime('%m月%d日 %H:%M')
UnicodeEncodeError: 'ascii' codec can't encode character u'\u6708' in position 2: ordinal not in range(128)

2. 原因分析

因为datetime.strftime()只接受str类型的字符串,不接受unicode类型的字符串。

3. 解决方案

方案一(推荐):传入str类型的参数

#coding:utf-8
from __future__ import unicode_literals
from datetime import datetime

now = datetime.now()
print now.strftime('%m月%d日 %H:%M'.encode('utf-8'))  # 指明str类型字符串


方案二(不推荐):设置运行时编码为utf-8

#coding:utf-8
from __future__ import unicode_literals
import sys
from datetime import datetime

reload(sys)
sys.setdefaultencoding('utf-8')

now = datetime.now()
print now.strftime('%m月%d日 %H:%M')


参考资料:

由__future__中unicode_literals引起的错误来研究python中的编码问题

黄聪:解决python中文处理乱码,先要弄懂“字符”和“字节”的差别

http://docs.python.org/2/library/datetime.html#datetime.date.strftime

http://docs.python.org/2.7/library/functions.html#getattr

http://docs.python.org/2/whatsnew/2.6.html?highlight=bytestring#pep-3112-byte-literals

http://www.cnblogs.com/huxi/articles/1897271.html

http://stackoverflow.com/questions/6269765/what-does-the-b-character-do-in-front-of-a-string-literal
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: