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'
View Code

相对应的,如果变量是中文的,那么相应的编解码结果如下:

# -*- 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'
View Code

对于带有中文的部分,如果修改相应的系统默认编码,那么使用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'
View Code

 

(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)
View Code

这里python默认把‘熊猫’按照ASCII解码成unicode,失败。指明'熊猫'的解码方式,可以成功。

>>> print u'hello'+ '熊猫'.decode('utf8')
hello熊猫
View Code

 

(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解码,所以解码出来乱码。
View Code
变量是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'>
View Code

(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": "中文"}
View Code

 

posted @ 2019-03-13 17:45  xue_shan  阅读(733)  评论(0)    收藏  举报