python字符编码
在用python处理字符时,最烦的就是遇到下面两种错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xb9 in position 0: ordinal not in range(128)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
不用想一定是编码的问题,以前遇到的时候就在字符后面encode('utf-8')、decode('utf-8')乱试一遍,多试几次就不报错了。今天又遇到这个问题,然后查了资料研究了一下背后的原因。
字符编码
字符编码常用的有ASCII、GB类、Unicode、UTF-8……
简单介绍一下:
- ASCII: 用一字节表示一个字符,最高位为0,可以表示128种字符,常用于英文环境。
- GB类: GB2312用两字节表示一个字符,第一字节小于127即和ASCII相同,如果大于127就表示汉字和相应的全角符号; GBK是GB2312的扩展。
- Unicode: 用多个字节表示一个字符,它将所有字符都包括在内。用于英文很浪费。
- UTF-8:Unicode的一种,将Unicode变为可变长度的字符,它可以使用1~4个字节表示一个字符,根据不同的字符而变化字节长度。
更多关于字符的阅读:
python的str和unicode
python2的basestring存在有str和unicode两个子类,python编码的坑就在这里;而python3就只有unicode,也就没有编码的问题了。以下仅讨论python2的情况。
python中默认的编码方式是unicode。而str是unicode经过编码后得到的。str包括utf-8, gbk等。
简单来说就是:
- unicode到str需要编码——encode('XXX'),这里的XXX表示str想要的编码方式。
- str到unicode需要解码——decode('XXX'), 这里的XXX表示str原本的编码方式。
看例子:
>>> a = u'你好'
>>> a
u'\u4f60\u597d'
>>> b = a.encode('utf-8') # unicode -> str
>>> b
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> c = a.encode('gbk')
>>> c
'\xc4\xe3\xba\xc3'
>>> d = b.decode('utf-8') # str -> unicode
>>> d
u'\u4f60\u597d'
>>> e = b.decode('gbk') # 本来是用utf-8编码的str,这里用gbk解码
>>> print e # 得到乱码的原因是解码不对
浣犲ソ
str的不同编码之间的转换
一个str类型的字符,可能拥有多种编码格式如utf-8,gbk,gb2312,还有hex,base64等。
- utf-8, gbk, gb2312这类编码需要通过Unicode转换
>>> a = u"你好"
>>> a
u'\u4f60\u597d'
>>> b = a.encode('utf-8')
>>> b
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> c = b.decode('utf-8').encode('gbk') #先utf-8解码到Unicode,再gbk编码
>>> c
'\xc4\xe3\xba\xc3'
>>> d = b.encode('gbk') # 直接对str进行gbk编码报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
- utf-8, gbk 到 hex, base64 直接encode
>>> b.encode('hex')
'e4bda0e5a5bd'
>>> c.encode('hex')
'c4e3bac3'
>>> b.encode('base64')
'5L2g5aW9\n'
>>> c.encode('base64')
'xOO6ww==\n'
>>> 'xOO6ww==\n'.decode('base64')
'\xc4\xe3\xba\xc3'
Comments