python的字符编码如果不弄明白,早晚会坑你一把的。python2 和python3的升级之一就是字符编码。python2的默认字符编码是ASCII ,而python3 的默认字符编码是unicode。
编码的起源
ASCII码是最早的字符编码,python诞生的时候没有考虑过其他国家也会使用计算机,使用python,于是在最初设计的时候就用ASCII作为默认的编码。ASCII码是8个字节,最多只能表示256个字符,肯定不够用呀,或者说只够老美用的,那其他国家怎么办。于是每个国家就自己整了一个对照表,比如我国就是gb2312(后来是gbk,汉子多了一些)。虽然每个国家都有自己的对照表,但是在自己的国家里面玩玩还可,出去可就不行了。就像语言一样,你去哪都说汉语,外国人听不懂呀,还搞毛线呀。必须有一个统一的编码出现才行,事后unicode就闪亮登场了。
unicode编码有各个国家编码的对照规则,所以能够显示各个国家的语言。这样夸国之间的编码问题就解决了。但是由于各国编码所占的字节不同,unicode编码在融合各国国家编码之后就变成了2个字节表示一个字符,(有的不常用的是4个字节)。这样就带来了两个问题
- 原来老美的英文文档存储空间直接扩大了一倍
- 当资源在网络传输中,消耗的带宽增加一倍
为了解决上面的问题,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。
python 2编码
python2 的默认编码是ascii,ascii不能表示中文。如果表示中文需要转换成支持中文的编码(utf-8,unicode,gbk)
注意:Unicode是编码相互转换的中介,因为它包含编码的转换关系。
指定文件编码 #-- coding:utf-8 --
#!/usr/bin/env python
s = "你好"
print s
结果报错:
SyntaxError: Non-ASCII character '\xe4' in file /home/liubo/docker-publish/publish_django/编码.py on line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
ascii编码是不支持中文的,需要指定文件编码
#!/usr/bin/env python
#-- coding:utf-8 --
s = "你好"
print s
结果:
你好
编码转换:
- Unicode是中间编码,如ascii转换成utf-8,需 ascii–>unicode–>utf-8
- decode 解码,是其他编码转换成unicode
- encode 编码,是unicode转换成其他编码
#!/usr/bin/env python
#-- coding:utf-8 --
s = "你好"
print s
print type(s)
s_uni = s.decode(encoding="utf-8")
print s_uni
print type(s_uni)
s_gbk = s_uni.encode(encoding="gbk")
print s_gbk
print type(s_gbk)
s_utf8 = s_uni.encode(encoding="utf-8")
print s_utf8
print type(s_utf8)
结果
你好
<type 'str'>
你好
<type 'unicode'>
���
<type 'str'>
你好
<type 'str'>
python3 编码
python3中编码有两种类型,一种是str,另外一种是bytes.
- str 就是unicode
- bytes是其他类型(utf-8,ascii,gbk等)
- 在内存中是unicode,在硬盘上或者网络传输时是bytes
s = "你好"
print (s)
print (type(s))
s_gbk = s.encode(encoding="gbk")
print (s_gbk)
print (type(s_gbk))
s_utf8 = s.encode(encoding='utf-8')
print (s_utf8)
print (type(s_utf8))
结果
你好
<class 'str'>
b'\xc4\xe3\xba\xc3'
<class 'bytes'>
b'\xe4\xbd\xa0\xe5\xa5\xbd'
<class 'bytes'>
总结:
编码尽量用utf-8格式,已经逐渐成为一种标准。
如果遇到乱码,从文件编码,解释器编码,终端编码,系统编码来排查问题。