目前python2.0还在使用,但可以看出python3.0才是未来的主流。因此本文主要研究的是Python3中的各编码问题。
UnicodeEncodeError错误:字符编码错误
python系统默认编码
在python2中,系统默认的编码方式是:ASCII码。字母、标点和其他字符只使用一个字节来表示,但对于中文字符来说,一个字节满足不了需求,因此碰到中文的时候就会乱码。
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>>
在Python3中,对中文进行了全面的支持(Python3 把系统默认编码设置为 UTF-8)。
>>> import sys
>>> sys.getdefaultencoding()
'utf-8'
>>>
所以在编写源代码文件xxx.py时需要注意:
- 如果源代码声明了Python不支持的编码格式,则程序将在编译期间抛出异常
python3文本字符和二进制数据
- str(用于Unicode文本,包括ASCII)
- bytes(用 于带有绝对字节值的二进制数据)
- bytearray(bytes的一种可变的形式)
Python3中文本字符和二进制数据区分得更清晰,分别用 str 和 bytes 表示。文本字符全部用 str 类型表示,str 能表示 Unicode 字符集中所有字符,而二进制字节数据用一种全新的数据类型,用 bytes 来表示。
Python3 中,在字符引号前加‘b’,明确表示这是一个 bytes 类型的对象,实际上它就是一组二进制字节序列组成的数据,bytes 类型可以是 ASCII范围内的字符和其它十六进制形式的字符数据,但不能用中文等非ASCII字符表示。
>>> a = b'\xe7\xa6\x85'
>>> a
b'\xe7\xa6\x85'
>>> type(a)
<class 'bytes'>
>>> c = b'张博轩'
File "<stdin>", line 1
SyntaxError: bytes can only contain ASCII literal characters.
>>>
python2 与 python3 字节与字符的对应关系
PYTHON2 | PYTHON3 | 表现 | 转换 | 作用 |
---|---|---|---|---|
str | bytes | 字节 | encode | 存储 |
unicode | str | 字符 | decode | 显示 |
编码和解码
str 与 bytes 之间的转换可以用 encode 和从decode 方法。
encode 负责字符到字节的编码转换。默认使用 UTF-8 编码转换。
decode 负责字节到字符的解码转换,通常使用 UTF-8 编码格式进行转换。
编码方式判断
如果一个字符串已经是unicode了,再进行解码则将出错,因此通常要对其编码方式是否为unicode进行判断:
isinstance(s, unicode) #用来判断是否为unicode
用非unicode编码形式的str来encode会报错
chardet模块
chardet是python的一个第三方库,常用于编码识别。
文件编码判断
import chardet
with open('text.txt', 'rb') as f:
data = f.readline()
tmp = chardet.detect(data)
print(tmp)
"""
{'encoding': 'ascii', 'confidence': 1.0}
"""
unicode和utf-8本质上是两个东西
- unicode 只是字符集,而不是编码方式
- utf-8 一种编码方式
utf-8是对unicode字符集进行编码的一种编码方式
同一文档有几种编码 decode报错解决UnicodeDecodeError
可以在decode()中加入参数。如:
decode('gb2312', 'ignore')
意思上忽略非gb2312编码的字符,这样就不会报错了。其他类似的参数如下:
- 默认的参数就是strict,代表遇到非法字符时抛出异常;
- 如果设置为ignore,则会忽略非法字符;
- 如果设置为replace,则会用?号取代非法字符;
- 如果设置为xmlcharrefreplace,则使用XML的字符引用。