python2编码问题
看了以下两篇博文的基础上,感觉自己明白了点。记录下。
http://www.cnblogs.com/yuanchenqi/articles/5938733.html
http://www.cnblogs.com/yuanchenqi/articles/5956943.html
python2的编解码的几个问题:
(1)两种数据类型unicode 和 str。
unicode-->str 的过程是编码,可以用encode('utf8')这种方式表示,也可以用str()把unicode变成str类型,
另外,str-->unicode 是解码过程,unicode(str),或者str.decode('utf8') 都可以。
但是python2中系统默认的编码是ASCII码,即使你在编辑.py 文件里声明了coding是utf8,那么在执行str(u‘\uXXXX’) 或者 unicode()时,默认还是使用ASCII码进行编解码。
除非使用代码改变system的default encoding。
如果变量是英文的,相应的编解码test如下:

import sys print(sys.getdefaultencoding()) # 定义a1是英文 str类型 a1 = "hello world" print "-----a1--------" print a1 print type(a1) print repr(a1) # str(str类型)直接返回str类型 print "-----b1--------" b1 = str(a1) print b1 print type(b1) print repr(b1) #unicode(str类型)返回通过ASCII解码方式成unicode print "-----c1--------" c1 = unicode(a1) print c1 print type(c1) print repr(c1) #用decode方式,把str解码成unicode,对应c1 print "-----d1--------" d1 = a1.decode('utf8') print d1 print type(d1) print repr(d1) # 定义a2是英文 unicode类型 print "-----a2--------" a2 = u'hello world' print a2 print type(a2) print repr(a2) # str(unicode类型)相当于用默认的ASCII码编码成str print "-----b2--------" b2 = str(a2) print b2 print type(b2) print repr(b2) #unicode unicode类型)不变 print "-----c2--------" c2 = unicode(a2) print c2 print type(c2) print repr(c2) # 用encode编码,对应b2部分 print "-----d2--------" d2 = a2.encode('utf8') print d2 print type(d2) print repr(d2) 运行结果: ascii -----a1-------- hello world <type 'str'> 'hello world' -----b1-------- hello world <type 'str'> 'hello world' -----c1-------- hello world <type 'unicode'> u'hello world' -----d1-------- hello world <type 'unicode'> u'hello world' -----a2-------- hello world <type 'unicode'> u'hello world' -----b2-------- hello world <type 'str'> 'hello world' -----c2-------- hello world <type 'unicode'> u'hello world' -----d2-------- hello world <type 'str'> 'hello world'
相对应的,如果变量是中文的,那么相应的编解码结果如下:

# -*- coding:utf-8 -*- import sys print(sys.getdefaultencoding()) # 定义a1是英文 str类型 a1 = "I am 熊猫" print "-----a1--------" print a1 print type(a1) print repr(a1) # str(str类型)直接返回str类型 print "-----b1--------" b1 = str(a1) print b1 print type(b1) print repr(b1) # #unicode(str类型)返回通过ASCII解码方式成unicode # print "-----c1--------" # c1 = unicode(a1) #运行结果:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 5: ordinal not in range(128) # print c1 # print type(c1) # print repr(c1) #用decode方式,把str解码成unicode,对应c1 print "-----d1--------" d1 = a1.decode('utf8') print d1 print type(d1) print repr(d1) # 定义a2是英文 unicode类型 print "-----a2--------" a2 = u'I am 熊猫' print a2 print type(a2) print repr(a2) # # str(unicode类型)相当于用默认的ASCII码编码成str # print "-----b2--------" # b2 = str(a2) #运行结果:UnicodeEncodeError: 'ascii' codec can't encode characters in position 5-6: ordinal not in range(128) # print b2 # print type(b2) # print repr(b2) #unicode unicode类型)不变 print "-----c2--------" c2 = unicode(a2) print c2 print type(c2) print repr(c2) # 用encode编码,对应b2部分 print "-----d2--------" d2 = a2.encode('utf8') print d2 print type(d2) print repr(d2) 运行结果: ascii -----a1-------- I am 熊猫 <type 'str'> 'I am \xe7\x86\x8a\xe7\x8c\xab' -----b1-------- I am 熊猫 <type 'str'> 'I am \xe7\x86\x8a\xe7\x8c\xab' -----d1-------- I am 熊猫 <type 'unicode'> u'I am \u718a\u732b' -----a2-------- I am 熊猫 <type 'unicode'> u'I am \u718a\u732b' -----c2-------- I am 熊猫 <type 'unicode'> u'I am \u718a\u732b' -----d2-------- I am 熊猫 <type 'str'> 'I am \xe7\x86\x8a\xe7\x8c\xab'
对于带有中文的部分,如果修改相应的系统默认编码,那么使用str或者unicode也不会出错:

# -*- coding:utf-8 -*- import sys print(sys.getdefaultencoding()) reload(sys) sys.setdefaultencoding('utf8') print(sys.getdefaultencoding()) # 定义a1是英文 str类型 a1 = "I am 熊猫" print "-----a1--------" print a1 print type(a1) print repr(a1) # str(str类型)直接返回str类型 print "-----b1--------" b1 = str(a1) print b1 print type(b1) print repr(b1) #unicode(str类型)返回通过ASCII解码方式成unicode print "-----c1--------" c1 = unicode(a1) print c1 print type(c1) print repr(c1) #用decode方式,把str解码成unicode,对应c1 print "-----d1--------" d1 = a1.decode('utf8') print d1 print type(d1) print repr(d1) # 定义a2是英文 unicode类型 print "-----a2--------" a2 = u'I am 熊猫' print a2 print type(a2) print repr(a2) # str(unicode类型)相当于用默认的ASCII码编码成str print "-----b2--------" b2 = str(a2) print b2 print type(b2) print repr(b2) #unicode unicode类型)不变 print "-----c2--------" c2 = unicode(a2) print c2 print type(c2) print repr(c2) # 用encode编码,对应b2部分 print "-----d2--------" d2 = a2.encode('utf8') print d2 print type(d2) print repr(d2) 运行结果: ascii utf8 -----a1-------- I am 熊猫 <type 'str'> 'I am \xe7\x86\x8a\xe7\x8c\xab' -----b1-------- I am 熊猫 <type 'str'> 'I am \xe7\x86\x8a\xe7\x8c\xab' -----c1-------- I am 熊猫 <type 'unicode'> u'I am \u718a\u732b' -----d1-------- I am 熊猫 <type 'unicode'> u'I am \u718a\u732b' -----a2-------- I am 熊猫 <type 'unicode'> u'I am \u718a\u732b' -----b2-------- I am 熊猫 <type 'str'> 'I am \xe7\x86\x8a\xe7\x8c\xab' -----c2-------- I am 熊猫 <type 'unicode'> u'I am \u718a\u732b' -----d2-------- I am 熊猫 <type 'str'> 'I am \xe7\x86\x8a\xe7\x8c\xab'
(2)python2,当unicode和str 相连时,默认的,Python2会按照默认编码,把str先变成unicode进行相连。

>>>print u'hello'+ '熊猫' Traceback (most recent call last): File "<input>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 0: ordinal not in range(128)
这里python默认把‘熊猫’按照ASCII解码成unicode,失败。指明'熊猫'的解码方式,可以成功。

>>> print u'hello'+ '熊猫'.decode('utf8') hello熊猫
(3)当使用print时,print A 相当于 sys.stdout.write(str(A))
Python2.7中调用print打印var 变量时,操作系统会对var做一定的字符处理:
如果var是str类型的变量,则直接将var变量交付给终端进行显示;
如果var变量是unicode类型,则操作系统首先将var编码成str类型的对象(编码格式取决于stdout的编码格式),然后再交由终端进行显示。
在终端显示时,如果str类型的变量的编码方式和终端设置的编码方式不一致,很可能会出现乱码问题。
以下分情况进行用代码进行实验:
变量是str类型的,在不同terminal下运行结果:

文件1: utf8编码的str类型的打印py2_utf8.py 文件2: gbk编码的str类型的打印py2_gbk.py 以上两个文件,在两种终端运行: 1). 在pycharm上执行,pycharm相当于sys.stdout.encoding 是UTF8的终端。 2). 在windows cmd上执行,cmd的编码方式是gbk # -*- coding:utf8 -*- # py2_utf8.py a = "I am 熊猫" print a print repr(a) print type(a) 在pycharm上,运行结果正常: 文件中定义的a,在内存中是utf8编码的字节码流,传到操作系统,操作系统不做任何操作,传给终端,终端按照pycharm终端的utf8解码,编解码对应,所以输出正常。 I am 熊猫 'I am \xe7\x86\x8a\xe7\x8c\xab' <type 'str'> 在windows cmd上运行: c:\Python27>python D:\python_project\for_python2\py2_utf8.py I am 鐔婄尗 'I am \xe7\x86\x8a\xe7\x8c\xab' <type 'str'> 文件中变量是utf8编码的字节流,到终端按照gbk解码,所以解码出来乱码。
变量是unicode类型的,在不同terminal下运行结果:

1. 文件以utf8 编码存储,py2_utf8_unicode.py 2. 文件以gbk编码存储,py2_gbk_unicode.py # -*- coding:utf8 -*- # py2_utf8_unicode.py b = u'I am 熊猫' print b print repr(b) print type(b) Pycharm 结果: I am 熊猫 u'I am \u718a\u732b' <type 'unicode'> CMD结果: c:\Python27>python D:\python_project\for_python2\py2_utf8_unicode.py I am 熊猫 u'I am \u718a\u732b' <type 'unicode'> # -*- coding:gbk -*- # py2_gbk_unicode.py b = u'I am 熊猫' print b print repr(b) print type(b) Pycharm下: C:\Python27\python.exe D:/python_project/for_python2/py2_gbk_unicode.py I am 熊猫 u'I am \u718a\u732b' <type 'unicode'> CMD下: c:\Python27>python D:\python_project\for_python2\py2_gbk_unicode.py I am 熊猫 u'I am \u718a\u732b' <type 'unicode'>
(4)print list和dict时中文显示编码问题

#-*-coding:utf-8 -*- a={'name': 'english'} b={'name': '中文'} print "a=", a print "b=", b import json result = json.dumps(b, encoding='UTF-8', ensure_ascii=False) print "b=", result pycharm中运行结果: a= {'name': 'english'} b= {'name': '\xe4\xb8\xad\xe6\x96\x87'} b= {"name": "中文"}