Python 2中的字符串分类
在Python 2中字符串,有两个类型,一个是str,一个是unicode。str可以理解为ASCII的字符列表,说白了,只能存储ASCII字符,如果赋个中文值,会报错;而unicode是支持非ASCII字符的。这个与C语言中的字符非常类似char[]只能存ASCII字符串,而wchar[]才可以存储Unidcode字符串。
可以用如下方式来安全的转换两种字符串:
1 2 3 4 5 6 7 8 9 10 11 |
|
对于字面字符串,前面加上u来标识是一个unicode,否则会当成str:
1 2 |
|
Python 3中的字符串分类
由于Python 2中的混乱,所以到了Python 3里面,有了新的定义,字符串类型是str,支持Unicode,另外多了一个类型bytes,可以理解为byte的列表,也即是0<=且<=256的无符号整数,或者说是ASCII字符,简单来理解意思是一样的。这个就与Java语言类似了,如同Java中一样,String支持unicode,另专门有byte类型。另外,对于字面字符串也无需要再要标识了。
str与bytes之间的关系与区别是,str是给人看的,而bytes是给机器看的,bytes是str的底层实现。所以,bytes处理起来更快,效率更高,一些底层的IO库以及像网络IO,用的数据 一般都是bytes。它们之间是可以互转的:
- str转为bytes叫encode
- bytes转为str叫decode
在转换的时候还需要指定编码格式,这个编码格式就是unicode的编码方式,默认是’utf-8’,这里就涉及Unicode编码解码的相关知识了,常见的就是’utf-8’,’unicode’,以及’gbk’等。可以用如下方法来安全的转换:
1 2 3 4 5 6 7 8 9 10 |
|
注意区分两个编码格式
需要注意区分两个编码格式的设置,一个是指定程序里面字符串的编码,如在encode()和decode()时指定编码格式。
另外,一个就是程序源文件的编码格式,这个容易被忽略,要详细说下:程序的源码,其实就是一个文本文件,对吧,那么这个文本文件也是要指定编码格式的,常规来说,Python程序应该都是ASCII字符,所以默认的呢Python解释器,是按照ASCII文本的方式来处理代码源文件,但我们代码里面是会出现Unicode字符的,比如字面字符串,或者写的注释,如果 不进行特殊的设置解释器会报错的,因为出现了它不认识的字符。这时就需要对源码文件设置一下编码格式,把这句加在代码源文件的最上面,就好了:
1
|
|
如何解决未知编码格式
关于编码最容易遇到的就是UnicodeDecodeError,后面跟着一坨详细信息,这个错误就是告诉你编码时出问题了,通常有两类错误:
UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe4 in position 0: ordinal not in range(128)
这个通常是在Python 2时会遇到,原因简单的来说就是把unicode当成了string,或者源码文件的编码格式不对。解决的办法就是按照 上面介绍的安全转换方法,另外要设置一下源码文件的编码格式,这个问题自然可解。
Python3.6 UnicodeDecodeError: ‘utf8’ codec can’t decode byte 0xb2 in position 24137: invalid start byte
这个通常是在Python 3时面遇到的,后面的具体信息会不一样,这个问题会发生在bytes转化为string,decode时会报出,原因就是指定的解码方式与真实的不匹配,无法成功decode,比如,bytes是「gtk」的,但是用’utf-8’去decode肯定会失败。这个问题,在写爬虫或者一些文本处理时经常遇到,因为来源的编码方式不固定。
这个问题,如果想要根解,必须预知来源bytes的编码格式,但这通常不可能,所以可行的一条方案是,用一坨编码方式来不停的尝试:
def safe_decode(source): encodeings = ['utf-8', 'gbk', 'utf-16'] for en in encodeings: try: return source.decode(en) except UnicodeDecodeError as e: print('Failed: ', e) return source