Python2在编译安装时可以通过参数 --enable-unicode=ucs2 或 --enable-unicode=ucs4分别指定使用2个字节或者4个字节表示一个unicode字符,python3默认使用4个字节表示一个unicode字符,无法改变
python2默认ucs2标准?
查看当前python环境unicode字符串占用空间:
import sys
print(sys.maxunicode)
# 65535 表示ucs2标准,2个字节表示一个unicode字符
# 111411 表示ucs4标准,4个字节表示一个unicode字符
编码与解码:
编解码本质上是一种映射关系,比如'a'用ascii编码表示为65,计算机存储的就是00110101,但是显示的时候计算机就去ascii表里查对应的是'a',就显示为'a'
ASCII与UTF-8:
ASCII以一个字节8个bit位表示一个字符,首位全是0,表示的字符集不够;
unicode编码系统是为了表达任意语言而设计的,为了防止存储上的冗余,比如ascii码对应的那部分,unicode采用了变长编码,因此给解码带来了困难,无法判断几个字节表示一个字符;
utf-8是针对unicode变长编码设计的一种前缀编码,根据前缀来判断几个字节表示一个字符,如果一个字节的第一位是0,则表示一个字节就是一个字符,如果第一位是1,则连续有多少个1就表示多少个字节表示一个字符
在计算机工作时,内存数据一直以unicode编码方式表示,当数据保存到磁盘或者网络传输时才会使用utf-8等编码进行操作
在python2中,有两种字符串类型:str和unicode。str存bytes数据,unicode村unicode数据
# coding:utf-8
# python2
s1 = '你'
s2 = u'你'
print(type(s1)) # str
print(repr(s1)) # '\xe4\xbd\xa0'
print(type(s2)) # unicode
print(repr(s2)) # u'\u4f60'
字节数据常用来存储和传输,unicode数据用来显示明文
无论是utf-8还是gbk都是一种编码规则,用来把unicode数据编码成字节数据
在python3中也只有两种字符串类型:str和bytes
str存unicode类型,相当于python2的unicode;bytes存bytes类型,相当于python2的str
python3中不会对bytes字节进行自动解码,文本总是unicode,由str类型表示;二进制由bytes表示
问题:下面的代码在python2会报错,在python3会正常输出
print('你好')
原因:python解释器类似于一个文本编辑器,python2默认ASCII码,python3默认UTF-8,可如下查看:
import sys
# python2输出ascii,python3输出utf-8
print(sys.getdefaultencoding())
因此当用python2解释器执行utf-8就会出现解码失败错误,而python3解释器默认编码为utf-8就不会报错。
在第一行加上#coding:utf-8 就是告诉解释器不要以默认编码方式去解码了,而是用utf-8来解码
因此当utf-8格式编码的代码在python2运行时就会显示正常了:
# coding:utf-8
# python2
import sys
print(sys.getdefaultencoding()) #ascii
print('你好') #你好
但是当在windows命令行通过python xxx.py来执行python程序时,因为cmd窗口默认位gbk编码,而python2中字符串的数据类型是str,相当于python3中的bytes类型;python3中字符串的数据类型是unicode
数据转换关系为:
bytes(python2的str)--> decode解码 --> str(python2的unicode)--> encode编码 --> bytes(python2的str)
因此在cmd窗口中,python2的字符串相当于python3的bytes类型,前面说过,字节数据常用来存储和传输,unicode数据用来显示明文,因此这里需要进行decode解码成unicode才可以正常显示,如果不进行解码操作,python2解释器就会进行自动以cmd窗口默认的gbk进行解码,显示的就是乱码。在代码里指定以utf-8解码就可以正常显示了
# coding:utf-8
import sys
print(sys.getdefaultencoding()) # ascii
a = '你好'
print(type(a)) # str(相当于python3中的bytes)
print(a.decode('utf-8')) #你好
而python3的字符串直接就是str(unicode)类型不需要decode解码就可以直接显示