Python2 和 Python3 编码问题

基本存储单元

  • 位(bit, b):二进制数中的一个数位,能够是0或者1,是计算机中数据的最小单位。
  • 字节(Byte,B):计算机中数据的基本单位,每8位组成一个字节。
  • 1B = 8b
  • 各类信息在计算机中存储、处理,至少须要一个字节的空间。

 

字节与字符

  • 计算机存储的一切数据都是由一串 0 和 1 组成的字节序列构成。
  • 字符就是一个符号,好比一个汉字、一个英文字母、一个标点均可以称为一个字符。

 

编码与解码

  • 咱们用编辑器打开的文本,看到的一个个字符,最终保存在磁盘上的时候都是以二进制字节序列形式存起来的。那么从字符到字节的转换过程就叫作编码(encode),反过来叫作解码(decode),二者是一个可逆的过程。编码是为了存储传输,解码是为了方便显示阅读。

 

编码规则

  • 编码是人们定义的一种规则,使字符能够根据该规则,转换为对应的字节,方便存储和传输,也可使字节转化成对应的字符用于显示、阅读。
  • 例如,按照 ASCII 编码进行转换,字符 A 对应的字节为 0100 0001,占用 1 个字节的大小,一个字节也就是8位,能够表示 0 - 255,对于英文来说 255 个字符已经足够显示全部的英文字符了,因此 ASCII(每一个 字符占用一个字节) 编码是美国的标准编码
  • 可是 ASCII 处理中文明显是不够的,中文不止 255 个汉字,因此中国制定了 GB2312 编码,用两个字节表示一个汉字。GB2312 还把 ASCII 包含进去了,同理,日文,韩文等等上百个国家为了解决这个问题就都发展了一套字节的编码,标准就愈来愈多,若是出现多种语言混合显示就必定会出现乱码
  • 因而 unicode 出现了,将全部语言统一到一套编码里,每个 unicode 字符占用两个字节的大小空间
  • 乱码问题解决了,可是若是内容全是英文,unicode 编码比 ASCII 须要多一倍的存储空间,同时若是进行网络传输也须要传输多一倍的数据
  • 因此出现了可变长的编码 "utf-8",把英文变长一个字节,汉字 3 个字节。特别生僻的变成4-6字节,若是传输大量的英文,utf-8做用就很明显了。

 

encode() 和 decode()

  • decode 英文意思为 解码,encode 英文意思为 编码
  • decode 的做用是将其余编码转换成 unicode编码,例如 str1.decode('gbk'),表示将 gbk 编码的字符串 str1 转换成 unicode 编码
  • encode 的做用是将 unicode 编码的字符串,转换成其余编码的字符串,例如str2.encode('gbk'),表示将 unicode 编码的字符串st2,转换为 gbk 编码
  • 在 Python2 中,windows 简体中文平台下,字符串表示是 GBK 编码,在 Linux 平台下表示为 UTF8编码,能够在字符串定义时,修改字符编码格式,定义为 unicode 编码,例如 a = u'你好'
  • 在 Python3中,全部系统平台下字符串都表示为 unicode 编码,
  • 所以在编码转换时,一般须要以 unicode 做为中间编码,先将其余编码的字符串解码(decode)成 unicode,再从 unicode 编码(encode)成另外一种指定编码。

 

UnicodeDecodeError 和 UnicodeEncodeError

环境:windows简体中文 + Python2.7,当前环境 str 默认显示编码为 gbk(Linux 环境中 Python2.7 默认显示编码为 utf8)python

>>> a = ''
>>> a
'\xc4\xe3'
# 对应 gbk 编码
>>> a.encode() UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128) # 当 a.encode() 执行时,python 解释器发现 a 的编码格式为 GBK ,可是只有 unicode 编码才能进行 encode,因此系统帮咱们执行了 a.decode().encode() # 在 python2 中系统默认的 encoding 编码为 ascii,因此至关于 a.decode('ascii').encode('ascii') # 查看系统默认 encoding 编码 >>> import sys >>> sys.getdefaultencoding() 'ascii' # 因 ascii 编码中不支持中文字符,因此在执行到 decode时就出现了报错 UnicodeDecodeError # 能够将 a 解码为 unicode,再编码为 utf8格式 >>> a.decode('gbk') u'\u4f60' >>> a.decode('gbk').encode('utf8') '\xe4\xbd\xa0' #在 pyhton2 中定义 unicode 编码的字符串 >>> b u'\u6211' >>> b.encode() UnicodeEncodeError: 'ascii' codec can't encode character u'\u6211' in position 0: ordinal not in range(128) # 在 python2 中系统默认的 encoding 编码为 ascii,因此至关于执行了 a.encode('ascii') # ascii 编码中不支持中文字符,因此出现了UnicodeEncodeError # 能够把字符串b编码为 uft8 或者 gbk 格式,由于这两种编码都支持中文字符 >>> b.encode('utf8') '\xe6\x88\x91' >>> b.encode('gbk') '\xce\xd2'

 

Python3 编码

在 Python3 中字符串统一使用 unicode编码,而且系统默认 encoding 为 utf8windows

  • unicode 对内存操做友好,由于每个字符占用的空间同样
  • utf-8对存储和传输友好,由于会对应的减小占用空间的大小
>>> import sys
>>> print(sys.getdefaultencoding())
utf-8

>>> a = "你好" >>> a.encode() b'\xe4\xbd\xa0\xe5\xa5\xbd'

>>> a.encode().decode() '你好' >>> a.encode('gbk').decode('gbk') '你好'

 

 

相关文章
相关标签/搜索