Python常见字符编码间的转换
1. 前⾔
  Python2.x和Python3.x在字符编码的设置上也有很⼤区别(Python3未来将是主流,所以Python3为主),今天我们就来⼀起学习下。
  上⼀篇⽂章⾥已经简述了Python的常见编码了,这⾥就不再赘述了,还不清楚的可以先去看下:
2. Unicode 和 UTF-8的爱恨纠葛
  U nicode 起到了2个作⽤:
1. 直接⽀持全球所有语⾔,每个国家都可以不⽤再使⽤⾃⼰之前的旧编码了,⽤unicode就可以了。(就跟英语是全球统⼀语⾔⼀样)
2. unicode包含了跟全球所有国家编码的映射关系。
  Unicode解决了字符和⼆进制的对应关系,但是使⽤unicode表⽰⼀个字符,太浪费空间。
  例如:利⽤unicode表⽰"Python"需要12个字节才能表⽰,⽐原来ASCII表⽰增加了1倍。
  由于计算机的内存⽐较⼤,并且字符串在内容中表⽰时也不会特别⼤,所以内容可以使⽤unicode来处理,但是存储和⽹络传输时⼀般数据都会⾮常多,那么增加1倍将是⽆法容忍的
  为了解决存储和⽹络传输的问题,出现了Unicode Transformation Format,学术名UTF,即:对unicode中的进⾏转换,以便于在存储和⽹络传输时可以节省空间!
  UTF-8:使⽤1、2、3、4个字节表⽰所有字符;优先使⽤1个字符、⽆法满⾜则使增加⼀个字节,最多4个字节。英⽂占1个字节、欧洲语系占2个、东亚语系占3个,其它及特殊字符占4个。
  UTF-16:使⽤2、4个字节表⽰所有字符;优先使⽤2个字节,否则使⽤4个字节表⽰。
  UTF-32:使⽤4个字节表⽰所有字符。
  总结:UTF 是为unicode编码设计的⼀种在存储和传输时节省空间的编码⽅案。
3. 字符在硬盘上的存储
  ⾸先要明确的⼀点就是,⽆论以什么编码在内存⾥显⽰字符,存到硬盘上都是2进制(0b是说明这段数字是⼆进制,0x表⽰是16进制。0x⼏乎所有的编译器都⽀持,⽽⽀持0b的并不多)。理解这⼀点很重要。
ascii编码(美国):
      l  0b1101100
    o  0b1101111
    v  0b1110110
    e  0b1100101
GBK编码(中国):
    ⽼  0b11000000 0b11001111
    男  0b11000100 0b11010000
    孩  0b10111010 0b10100010
  还要注意的⼀点是:存到硬盘上时是以何种编码存的,再从硬盘上读出来时,就必须以何种编码读(开头声明或转换),要不然就乱了。
4. 编码的转换
  虽然有了unicode and utf-8 ,但是由于历史问题,各个国家依然在⼤量使⽤⾃⼰的编码,
  ⽐如中国的windows,默认编码依然是gbk,⽽不是utf-8。
  基于此,如果中国的软件出⼝到美国,在美国⼈的电脑上就会显⽰乱码,因为他们没有gbk编码。
  所以该怎么办呢?
  还记得我们讲unicode其中⼀个功能是其包含了跟全球所有国家编码的映射关系,这时就派上⽤场了。⽆论你以什么编码存储的数据,只要你的软件在把数据从硬盘读到内存⾥,转成unicode来显⽰,就可以了。由于所有的系统、编程语⾔都默认⽀持unicode,那你的gbk软件放到美国电脑上,加载到内存⾥,变成了unicode,
  中⽂就可以正常展⽰啦。
1. 解释器到代码⽂件,把代码字符串按⽂件头定义的编码加载到内存,转成unicode
2. 把代码字符串按照语法规则进⾏解释
3. 所有的变量字符都会以unicode编码声明
  在py3上把你的代码以utf-8编写,保存,然后在windows上执⾏。
  发现可以正常执⾏!
  其实utf-8编码之所以能在windows gbk的终端下显⽰正常,是因为到了内存⾥python解释器把utf-8转成了unicode,但是这只是python3, 并不是所有的编程语⾔在内存⾥默认编码都是unicode,⽐如万恶的python2 就不是,它是ASCII(龟叔当初设计Python时的⼀点缺陷),想写中⽂,就必须声明⽂件头的coding为gbk or utf-8, 声明之后,python2解释器
  仅以⽂件头声明的编码去解释你的代码,加载到内存后,并不会主动帮你转为unicode,也就是说,你的⽂件编码是utf-8,加载到内存⾥,你的变量字符串就也是utf-8, 这意味着什么?意味着,你以utf-8编码的⽂件,在windows是乱码。
  其实乱是正常的,不乱才不正常,因为只有2种情况,你的windows上显⽰才不会乱。
Python2执⾏过程
  Python2并不会⾃动把⽂件的编码转为Unicode存在内存中。
1. 字符串以GBK格式显⽰
2. 字符串是unicode编码
  所以我们只有⼿动转,Python3 ⾃动把⽂件编码转为unicode必定是调⽤了什么⽅法,这个⽅法就是,decode(解码)和encode(编码)  例如:
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
s = '匆匆'
print(s)
s1 = s.decode("utf-8") # utf-8 转成 Unicode,decode(解码)需要注明当前编码格式
print(s1,type(s1))
s2 = s1.encode("gbk") # unicode 转成 gbk,encode(编码)需要注明⽣成的编码格式
print(s2,type(s2))
s3 = s1.encode("utf-8") # unicode 转成 utf-8,encode(编码)注明⽣成的编码格式
print(s3,type(s3))
  ⽂件在Python2和Python3环境下运⾏结果的区别,如下所⽰:
#coding:utf-8
s = "你好,中国!"
print(s)    # Python2输出乱码,Python3正常输出
print(type(s))    # 均输出 <type 'str'>
#解码成unicode
s1 = s.decode("utf-8")
print(s1)    # Python2中输出 “你好,中国!”,Python3显⽰'str'对象没有属性'decode'
print(type(s1))  # Python2中输出 <type 'unicode'>  Python3中输出 <class 'str'>
#编码成gbk 或 utf-8
s2 = s1.encode('gbk')
print(s2)      # Python2中输出 “你好,中国!”
print(type(s2))    # Python2中输出 <type 'str'>
s3 = s1.encode('utf-8')
print(s3)      # Python2输出乱码,
print(type(s3))    # 输出 <type 'str'>
  编码相互转换的规则如下:
5. 如何验证编码转对了呢?
1. 查看数据类型,python 2 ⾥有专门的unicode 类型
2. 查看unicode编码映射表
  unicode字符是有专门的unicode类型来判断的,但是utf-8,gbk编码的字符都是str,你如果分辨出来的当前的字符串数据是何种编码的呢?  有⼈说可以通过字节长度判断,因为utf-8⼀个中⽂占3字节,gbk⼀个占2字节。
  看输出的字节个数,也能⼤体判断是什么类型。精确的验证⼀个字符的编码呢,就是拿这些16进制的数跟编码表⾥去匹配。
  关于 Unicode 与 GBK 等编码对应关系(以中⽂"路"为例):
unicode编码转换二进制
  完整的编码对应表可到这个⽹站下载:unicode与gbk的映射表/charts/
6. Python bytes类型
  把8个⼆进制⼀组称为⼀个byte,⽤16进制来表⽰。为的就是让⼈们看起来更可读。我们称之为bytes类型,即字节类型。
  python2的字符串其实更应该称为字节串。通过存储⽅式就能看出来,但python2⾥还有⼀个类型是bytes呀,难道⼜叫bytes⼜叫字符串?
  嗯,是的,在python2⾥,bytes == str ,其实就是⼀回事。
  除此之外呢, python2⾥还有个单独的类型是unicode , 把字符串解码后,就会变成unicode。
>>> s
'\xe8\xb7\xaf\xe9\xa3\x9e'#utf-8
>>> s.decode('utf-8')
u'\u8def\u98de'#unicode 在unicode编码表⾥对应的位置
>>> print(s.decode('utf-8'))
路飞#unicode 格式的字符
  Python2的默认编码是ASCII码,当后来⼤家对⽀持汉字、⽇⽂、法语等语⾔的呼声越来越⾼时,Python于是准备引⼊unicode,但若直接把默认编码改成unicode的话是不现实的,因为很多软件就是基于之前的默认编码ASCII开发的,编码⼀换,那些软件的编码就都乱了。所以Python 2就直接搞了⼀个新的字符类型,就叫unicode类型,⽐如你想让你的中⽂在全球所有电脑上正常显⽰,在内存⾥就得把字符串存成unicode类型。
>>> s = "路飞"
>>> s
'\xe8\xb7\xaf\xe9\xa3\x9e'
>>> s2 = s.decode("utf-8")
>>> s2
u'\u8def\u98de'
>>> type(s2)
<type 'unicode'>
  注意: 
  Python3 除了把字符串的编码改成了unicode, 还把str 和bytes 做了明确区分, str 就是unicode格式的字符, bytes就是单纯⼆进制啦。  在py3⾥看字符,必须得是unicode编码,其它编码⼀律按bytes格式展⽰。
  Python只要出现各种编码问题,⽆⾮是哪⾥的编码设置出错了
  常见编码错误的原因有以下这些:
Python解释器的默认编码
Python源⽂件⽂件编码
Terminal使⽤的编码
操作系统的语⾔设置
  总结:
   python3 
1. ⽂件默认编码是utf-8 , 字符串编码是 unicode
2. 以utf-8 或者 gbk等编码的代码,加载到内存,会⾃动转为unicode正常显⽰。
   python2 
1. ⽂件默认编码是ascii , 字符串编码也是 ascii , 如果⽂件头声明了是gbk,那字符串编码就是gbk。
2. 以utf-8 或者 gbk等编码的代码,加载到内存,并不会转为unicode,编码仍然是utf-8或者gbk等编码。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。