一文了解py2/py3编码问题
py2和py3都使用unicode作为内存代码,简称内码。当保存在python解释器内存中的文本输出到屏幕、编辑器或保存到文件中时,应将内码转换为utf8或gbk等编码格式;同样,当python解释器从输入设备接收文本或从文件读取文本时,应将utf8或gbk等编码转换为unicode编码格式。
因此,无论是py2还是py3,都想要unicode、utf8、如果在gbk等编码格式之间转换,下图是通用的:
我们之所以感到困惑,是因为py2和py3为这些编码格式指定了令人困惑的名字。
py2字符串有两种类型:unicode类型和str类型。
py2的unicode类型是unicode编码,py2的str类型一般是指除unicode编码外的所有编码,包括ascii编码、utf8编码、gbk编码、cp936编码等。
py3字符串也有两种类型:bytes类型和str类型。py3的str类型是unicode编码,py3的bytes类型一般是指除unicode编码外的所有编码,包括ascii编码、utf8编码、gbk编码、cp936编码等。
同样的str类型,在py2和py3中完全颠倒!下图添加了一点内容,更有利于理解编码问题。
接下来,让我们进行实战演练。
>>>s='abc天圆地点' >>>type(s) <class'str'> >>>len(s) 7 >>>s 'abc天圆地点' >>>print(s) 天圆地点abc >>>s.encode('unicode-escape') b'abc\u5929\u5706\u573;
无论是否在字符串前添加u,只要b不在字符串前使用,IDLE中定义的字符串都是unicode编码,即py3<class ‘str’>,它的长度是字符的数量,而不是字节的数量。我们将unicode字符串“abc天圆”转换为utf8编码:
>>>s_utf8=s.encode('utf8') >>>type(s_utf8) <class'bytes'> >>>len(s_utf8) 15 >>>s_utf8 b'abcxe5\xa4\xa9cx86\xe5cxb0\xe6\xb96; >>>print(s_utf8) b'abcxe5\xa4\xa9cx86\xe5cxb0\xe6\xb96; >>>s_utf8.decode('utf8') 'abc天圆地点'
utf8编码是bytes类型(字节码),长度是字节数量。我们将unicode字符串“abc天圆”转换为gbk编码:
>>>s_gbk=s.encode('gbk') >>>type(s_gbk) <class'bytes'> >>>len(s_gbk) 11 >>>s_gbk b'abc\xcc\xecxd4\xb2\xb5\xd8\xb7xbd' >>>print(s_gbk) b'abc\xcc\xecxd4\xb2\xb5\xd8\xb7xbd' >>>s_gbk.decode('s_gbk') 'abc天圆地点'
gbk编码也是bytes类型(字节码),长度也是字节数量。我们来看看不同编码的字节码是否可以连接:
>>>ss=s_utf8+s_gbk >>>ss b'abcxe5\xa4\xa9\xe5cx86\xe5cxb0\xe6\xb9abc\xcc\xecxd4\xb2\xb5\xd8\xb7xbd' >>>ss.decode('utf8') Traceback(mostrecentcalllast): File"<pyshell#64>",line1,in<module> ss.decode('utf8') UnicodeDecodeError:'utf-8'codeccan'tdecodebyte0xcinposintion:invalidcontinuationbyte >>>ss.decode('gbk') 'abc澶╁浑版abc天圆地方' >>>ss.decode('utf8','ignore') 'abc天圆地abcc天圆地abc天圆地abcԲط' >>>ss.decode('gbk','ignore') 'abc澶╁浑版abc天圆地方'
可以看出,除非使用ignore参数,否则可以连接不同编码的字节码,但一般不能解码为unicode(字符串)。
python学习网,免费在线学习python平台,欢迎关注!