python: 2.7.10
问题类似如下:
# en_name-->unicode
>>> en_name=u'zhongguo'
# cn_name-->str
>>> cn_name=u'中国'.encode('utf-8')
>>> """en_name: %s, cn_name: %s""" % (en_name, cn_name)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
从上可知,当unicode,str同时存在时,报错了
解决思路
1.只有unicode或者str,会不会报错
>>> """en_name:%s""" % (en_name)
u'en_name:zhongguo'
>>> """cn_name:%s""" % (cn_name)
'cn_name:\xe4\xb8\xad\xe5\x9b\xbd'
没有报错,而且你会发现,当参数为unicode, 返回结果也是unicode,如果是str,结果就是str
2.如果包含了unicode和str,结果是什么类型呢?
>>> """en_name:%s, cn_name:%s""" % (en_name, 'zhongwenming')
u'en_name:zhongguo, cn_name:zhongwenming'
结果表明,是unicode类型
因此,我们猜测当参数既有unicode又有str,%到底发生了什么
"""en_name: %s, cn_name: %s""" % (en_name, cn_name)
将参数转换成unicode
1. unicode(en_name) ---> pass
2. unicode(cn_name) ---> fail
报UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
如果是这样的话,一切就解释的通了,
比如:
参数只有str类型的话,将每个参数str(params), 不会报错
参数只有unicode类型的话,将每个参数unicode(params), 也不会报错
只有混合使用的话,并且str中有非ASCII码时,就会报错
如果将% 替换为format就不会报错,这是为什么了?
>>> """en_name: {}, cn_name: {}""".format(en_name, cn_name)
'en_name: zhongguo, cn_name: \xe4\xb8\xad\xe5\x9b\xbd'
statement % params
statement.format(params)
这是因为format跟%不一样的地方,
format的返回类型与statement有关
%的返回类型与params有关
所以使用了format, statement是str类型,因此str()作用所有参数,没有报错
>>> u"""en_name: {}, cn_name: {}""".format(u'中国', u'中'.encode('utf-8'))
报错UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
题外话:
1.为什么用%, 而不用format
项目是很老的项目,之前很多代码都使用了这种方式。所以很难说全部改掉这种用法