由于工作集群中部署的是Python2.7版本,缺乏python3的应用环境,因此将Python2.7中的编解码问题总结如下。
1. ASCII 、GB2312、Unicode 、UTF-8的关系:
1.1 ASCII(编码方式):
计算机在程序执行时只能识别二进制数,早期为了能够表示英文字符ABCD等,美国发明了ASCII码的编码方式。ASCII码将128个常用字符与8位二进制数一一对应,例如空格的ASCII码是32(二进制00100000),字母A是65等;由于编码128个字符只需占用7位二进制数(2^7=128), 因此ASCII码的8位数中的最高位统一规定为0。
1.2 GB2312(编码方式):中文汉字字符众多,一个字节只能表示256个符号,因此开发出GB2312采用2个字节表示一个汉字,因此理论可以表示出256^2=65536个符号,实际收录6763个
1.3 GBK(编码方式): 采用双字节表示,收录21886个汉字和多个图像符号,向下兼容GB2312。
1.4 Unicode(字符集、编码标准):Unicode不是编码方式, 是统一了全世界符号的字符集合,采用2个字节(十六进制数)规定了每个符号的二进制码,计算机内存中统一使用Unicode编码,但由于编码位数众多,极大浪费了存储空间,因此在存储或传输数据时会利用UTF-8等编码方式对unicode进行转换。
1.5 utf-8 (编码方式):是互联网使用最广的Unicode的实现方式,utf-8是变长的,使用1~4个字节,一个字符的utf-8编码若首位为0,则只包含一个字节,若首位为1,连续1的个数即为该字符占用的字节数
2 字符在计算机中的编码方式
2.1 终端显示字符的编码方式
windows下的终端是cmd,中文版windows默认为gbk编码,向下兼容gb2312;
linux下的终端是terminal,多数发行版linux的默认utf8编码,如zh_CN.utf8和en_US.utf8都是utf8编码,字符量相当。(zh_CN.utf8和en_US.utf8主要是语言环境上的区别,如时间、菜单、界面语言的显示等。)
2.2 文本文件的编码
文本文件的编码方式取决于编辑器,例如可以在py文本开头位置指定编码格式:#coding:utf-8
2.3 应用程序的内部编码
java和python的内部字符编码是utf-16,两者都支持用不同的编码方式对字节(byte)进行解码得到字符。
3 字符与字节的关系
计算机内部信息采用二进制存储,8个二进制位bit组合出一个字节,能表示2^8=256种状态;字节通过解码decode得到字符;字符通过编码encode得到字节,编解码的转换如下图所示。
4 #coding:utf-8 和 #-*-coding:utf-8-*- 的区别
在python2.7指定编码方式时,#coding:utf-8 和 #-*-coding:utf-8-*- 没有实质区别,事实上包含coding:utf-8或coding=utf-8的字符串均可识别,甚至是 #xxxxcoding:utf8 xxxx 也可以,但记得utf8后要接空格后再接其他字符。
5 #encoding:utf-8 和 sys.setdefaultencoding('utf-8')的区别
5.1 #encoding:utf-8
#用于告诉Python解释器该py文件用utf-8编码,指定后可用于解析代码中出现的中文,例如中文注释等;若不指定编码方式,则解释器默认使用ascii编码。
5.2 sys.setdefaultencoding('utf-8')
#用于指定在编解码时使用的默认方式,调用代码为:
import sys
reload(sys) #重新加载是因为首次加载时删除了sys中的setdefaultencoding(可能出于安全考虑)
sys.setdefaultencoding('utf-8') #指定在编码和解码时使用的默认方式
代码中对sys进行重新加载是由于首次加载时解释器删除了sys中的setdefaultencoding()方法(可能出于安全考虑),若不重加载则会因找不到setdefaultencoding()方法而报错。
6 编码解码在python2.7的应用实例
6.1 在linux终端下,使用unicode('汉字','gb2312')报错,这是由于字符串'汉字'在linux下默认为utf-8编码,因此无法通过gb2312转换为Unicode,正确使用应为unicode('汉字','utf-8');同理在windows中使用unicode('汉字','utf-8')会报错,应该使用unicode('汉字','gb2312')。
6.2 在linux终端下,'汉字'.decode('gbk')不会报错,这是由于省略了采用默认方式utf-8进行编码的过程,程序会先通过utf-8转换为unicode,再用gbk进行解码。(如果是在py文件中,则要先对默认编码方式进行指定:import sys; reload(sys); sys.setdefaultencoding('utf-8'))。
6.3 打印字符时,若字符的编码方式与shell不一致会出现乱码,而在打印unicode的时候shell会自动对其解码,这时就不会乱码。
6.4 如何输出含有中文的list:print(','.join(data))
6.5 如何输出含有中文的以tuple为元素的list,例如[('卧槽','sad'),('sd','算法')]:','.join(map(lambda x: ','.join(x),a))
参考资料:
http://www.pulpcode.cn/2014/12/23/python-encode/ python中的str与unicode处理方法
https://www.cnblogs.com/liaohuiqiang/p/7247393.html python2.7中的字符编码问题
https://www.zhihu.com/question/28164512?sort-created 知乎Kenneth的回答