前言
python中编码问题一直让人头大,这里好好的记录一下。
用于人类看的文本叫做明文。从明文到编码文本的转换称为“编码”,从编码文本又转回成明文则为“解码”。
编码文本通常用于计算机的解释文本。
python2的编码
python2中字符串有两种基本类型分别是str和unicode。
str和unicode都是basestring的子类。查看源码我们发现在python2中str=bytes。
str是unicode这个字符串经过编码(utf8,gbk等)后的字节组成的序列。
#coding=utf-8
s='编码problem'
print(s)#编码problem
print(len(s))#13
print(repr(s))#\xe7\xbc\x96\xe7\xa0\x81problem
print(type(s))#<type 'str'>
print(isinstance(s,bytes)) #True
#总结:python2中中文默认是以str类型存储的。汉字是字节的方式存储,一个汉字占两个字节。
s=u'编码problem'
print(s)#编码problem
print(len(s))#9
print(repr(s))#u'\u7f16\u7801problem'
print(type(s))#<type 'unicode'>
#总结:unicode的字符是一个字占一个字符的
a='hello'+u'alex'
print(a)#helloalex
print(type(a))#unicode
#说明我们在进行拼接的时候自动把bytes类型转成了unicode
print('你好'+'alex')#你好alex
print(u'你好'+'alex')#你好alex
print(u'你好'+u'詹姆斯')#你好詹姆斯
print('你好'+u'alex')#UnicodeDecodeError: 'gb2312' codec can't decode bytes
print(u'你好'+'詹姆斯')#UnicodeDecodeError: 'gb2312' codec can't decode bytes
#这就是那些可恶的 UnicodeError 。你的代码中包含了 unicode 和 byte 字符串,只要数据全部是 ASCII 的话,所有的转换都是正确的,一旦一个非 ASCII 字符偷偷进入你的程序,那么默认的解码将会失效,从而造成 UnicodeDecodeError 的错误。
python2 悄悄掩盖掉了 byte 到 unicode 的转换,让程序在处理 ASCII 的时候更加简单。你复出的代价就是在处理非 ASCII 的时候将会失败。
我们再来看看basestring的两个实例的方法。再来理解一下。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xlMW4Hdi-1588595925359)(https://s1.ax1x.com/2020/03/22/8IDqhT.png)]
具体代码:
# coding:utf8
u = u'苑'
print repr(u) # u'\u82d1'
# print str(u) #UnicodeEncodeError
s = u.encode('utf8')
print repr(s) # '\xe8\x8b\x91'
print s # 苑
u2 = s.decode('utf8')
print repr(u2) # u'\u82d1'
python3的编码
在python3中字符串也有两种类型。就是str和bytes两种。这的str类型实际上就是python2中的unicode。
python3最重要的新特性大概要算是对文本和二进制数据作了更为清晰的区分。
文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。python3不会以任意隐式的方式混用str和bytes,正是这使得两者的区分特别清晰。你不能拼接字符串和字节包,也无法在字节包里搜索字符串(反之亦然),也不能将字符串传入参数为字节包的函数(反之亦然)。这是件好事。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mJllUwcS-1588595925362)(https://s1.ax1x.com/2020/03/22/8IckdA.png)]
也就是说python3中不能使用bytes拼接str。
print('hello'+b'alex')#TypeError: can only concatenate str (not "bytes") to str
注意:无论py2,还是py3,与明文直接对应的就是unicode数据,打印unicode数据就会显示相应的明文(包括英文和中文)
python3中在网络上传输的时候使用的bytes。
python3中str和bytes类型的转换方式:这是在utf8编码下的转换
#str转bytes
s='詹姆斯'
##方式一:
print(bytes(s,'utf8'))
##方式二:
print(s.encode('utf8'))
#bytes转str
b=b'\xe5\x8b\x92\xe5\xb8\x83\xe6\x9c\x97'
##方式一
print(str(b,'utf8'))
##方式二
print(b.decode('utf8'))
编码问题
为什么python2中文件里有中文,不在文件开头写“#coding=utf-8”就会报错呢?而python3中为什么就没有这个问题呢?
因为python2的默认编码是gb2312或者ascii。而python3中的默认编码是utf-8。所以程序可以出现中文。查看默认编码方式:sys.getdefaultencoding()
那句话就是告诉python2.7解释器,解释py文件声明下面的内容按utf8编码。
每个文件保存到磁盘上都需要一种编码方式。编译器解释同样也需要一种编码方式。显示器同样也是一种编码方式。
这三种编码保持一致才能让程序正常运行。python3输出的字符串默认是unicode。所有的显示器都能够理解。
而python2中默认输出的是str类型。而str类型是unicode使用utf-8或者gbk等编码方式的字符。所以显示的时候会出现乱码问题。最简单的解决办法是把输出的字符串转成unicode就可以。当然也可以让输出的编码方式和显示器的编码方式一致都是gbk或者utf-8等。
在python2中我们可以通过“#coding=gb2312”来设置编码方式。
#coding=gb2312
s='詹姆斯'
print(s)
这个程序就可以在cmd里就可以正常显示。这样就保证了编码一致。
本文深入解析Python2和Python3中字符串编码的区别,探讨str、unicode和bytes类型,以及它们之间的转换。文章通过实例演示如何避免UnicodeError,确保跨平台编码一致性。

被折叠的 条评论
为什么被折叠?



