python py2与py3的编码问题
一:什么是编码
将明文转换为计算机可以识别的编码文本称为“编码”。反之从计算机可识别的编码文本转回为明文为“解码”。
那么什么是明文呢,首先我们从一段信息说起,消息以人们可以理解,易懂的表示存在,我们把这个表示为明文(plain text)。对于说英文的人,纸张上打印的或者屏幕上显示的英文都算是明文。
二:都有什么编码格式?
1:ASCII
计算机上的数据都是以二进制的形式存储的,1个字节(8比特)可以表示256种状态,英文只有26个字符,再加上一些特殊的字符,使用128个就够了,计算机就可以使用127个不同字节来表示英文文字,这就是ASCII码
2:GB2312
计算机进入中国后,无法显示中文,一个字节已经被占满了,我国重新制定了一个编码表,将扩展的第八位对应的拉丁文全部删掉,规定一个小于127的字符与原来的意义相同,当两个大于127的字符连接在一起的时候,就表示一个汉字,前面一个字节为高字节,后面一个字节为低字节,这样就可以表示7000多汉字,这种编码叫做GB2312。GB2312是对ASCII的中文扩展
3:GBK和GB18030
由于汉字的数量太大,GB2312是不能满足需求,后面规定只要第一个字节大于127就固定表示一个汉字,不管后面的是不是扩展字符里面的内容,扩展后的编码称为GBK,GBK包括了GB2312的所有内容,同时增加了近20000个新的汉字和符号
4:Unicode
在uincode出现之前,每隔国家都搞自己的编码,彼此之间互补支持,带来了许多不方便,国际标准组织提出来一个统一的编码标准:unicode
unicode用两个字符来表示一个字符,可以提供65535种字符,足够覆盖世界上所有的字符
5:UTF-8
unicode的出现,提供了统一的标准,但对于英文世界来说,一个字节完全够用,如果使用unicode会浪费大量的空间,为了解决这个问题提出来utf-8,一种针对unicode的可变长度字符串,可以使用1-4个字符表示一个符号,根据不同的符号变化字节长度,当字符在ASCII编码范围内,用一个字节表示,兼用ASCII。
使用这样编码的好处是,虽然内存汇总的数据都是unicode,但是当数据保存到磁盘或者用于网络传输时,使用utf-8会节省更多的流量和硬盘空间。
unicode和utf-8的关系:unicode是内存编码表示方案,而utf-8是如何保存和传输unicode的方案
三:python2.x的编码
在python2.x中,有两种字符串类型:str类型和unicode类型。这两个类型只是python定义的两个名字,关键还要看这两种数据类型在内存中的存储方法是什么
str和unicode都是basestring的子类。严格意义上说,str其实是字节串,它是unicode经过编码后的字节组成的序列。
而unicode是一个字符串,str是unicode这个字符串经过编码(utf8,gbk等)后的字节组成的序列。
unicode才是真正意义上的字符串,对字节串str使用正确的字符编码进行解码后获得
在Py2里,str=bytes。
py2编码的最大特点是Python 2 将会自动的将bytes数据解码成 unicode 字符串
所以在2里我们可以将字节与字符串拼接。
Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> s = '学习' >>> print type(s) <type 'str'> >>> print repr(s) '\xd1\xa7\xcf\xb0'
>>> s = u'学习'
>>> print type(s)
<type 'unicode'>
>>> print repr(s)
u'\u5b66\u4e60'
由上面的例子可以看出str和unicode分别存储的是字节数据和unicode数据
但是,python2.x悄悄掩盖掉了byte到unicode的转换,只要数据全部是ASCII的话,所有的转换都是正确的,一个一个非ASCII的字符进入你的程序,那么默认的解码将会失效,从而造成unicodedecodeerror的错误,py2编码让程序在出路ASCII的时候非常简单,付出的代价就是在处理非ASCII的时候将会失败。
四:python3.x的编码
python3.x也有两种数据类型,str和bytes;str类型存unicode数据,bytes类型存bytes数据,
python3.x将utf-8或者gbk等编码的字节数据转化为python3.x的str类型,utf-8编码的bytes<–>str
python2.x将utf-8或者gbk等编码的字节数据转化为python2.x的unicode类型,utf-8编码的str<–>unicode
python3.x的编码思想就是它清晰的将文本和二进制区分开了,不会对bytes字节进行自动编码。文本总是unicode,由str类型表示,二进制数据则由bytes类型表示,Python 3不会以任意隐式的方式混用str和bytes,将两者明确地区分开。基于此,Python3中不能拼接字符串和字节包,也不可以在字节包里搜索字符串(反之亦然),也不能向使用字符串参数的函数中传入字节包参数(反之亦然)。
######在python2.x####### print(b'hello'+'world') 会输出 helloworld ######在python3.x####### print(b'hello'+'world') 会输出 TypeError: can't concat str to bytes
五:文件存储读取过程中的编码问题
对于文本编辑器word等软件,当我们在这些软件上编辑文字的时候,无论是什么语言的文字或符号,计算机都是无法识别的。
那么在保存之前数据是通过什么形式存在内存的呢?
是unicode数据,为什么要存unicode数据,这是因为无论世界上的任何字符它都有唯一编码对应,兼容性是最好的。
当我们保存了存到磁盘上的数据又是什么呢?
是通过某种编码方式编码的bytes字节串。比如utf8---一种可变长编码,很好的节省了空间;还可以是gbk等编码方式。
在我们的文本编辑器软件都有默认的保存文件的编码方式,比如utf-8,gbk等。当我们保存的时候,这些编辑软件已经”默默地”做了编码工作。
那当我们再打开这个文件时,软件又默默地给我们做了解码的工作,将数据再解码成unicode,然后就可以呈现明文给用户了!
所以,unicode是离用户更近的数据,bytes是离计算机更近的数据。
六:编码与程序运行的关系
编写python代码一般会用到pycharm ,sublime等软件,而代码文件的创建,保存,执行等过程就伴随着编码解码流程,使用pycharm创建的hello.py文件,当我们保存的时候,文件就以pycharm默认的编码方式保存到磁盘,关闭文件再打开,pycharm就会以默认的编码方式对该文件打开后读到的内容就行解码,转成unicode到内存我们就看到了我们的明文;
而如果点开运行按钮或者在命令行运行该文件时候,python解释器就会被调用,打开文件,然后将存储在磁盘上的bytes数据解码成unicode数据,这个过程和编译器是一样的,不同的是解释器将会把这些unicode数据翻译成c代码再转成二进制的数据流,最后通过控制操作系统调用cpu来执行这些二进制数据,整个过程才算结束,
python2.x默认的是ASCII码,python3.x默认的是utf-8,可以通过下面的方式查询:
import sys
print(sys.getdefaultencoding())
七:print语句和print函数的区别
print语句
在python2.x中,print语句最简单的使用形式是
print hello world!
这相当于执行了
sys.stdout.write(‘’。join(map(str,[hello world!]))+'\n')
如果以逗号为分隔符,传递额外的参数,这些参数会被传递到str()函数,最终打印的时候,每个参数之间会空一行。
从2.0版本开始,python引入了print>>的语法。作用是重定向print语句最终输出的字符串的文件
例如:
print>>output 相当于 output.write(str(hello)+'\n')
print函数
如果用python来实现print的函数,他的函数定义应该是这样的
import sys def print(*objects, sep=None, end=None, file=None, flush=False): """A Python translation of the C code for builtins.print(). """ if sep is None: sep = ' ' if end is None: end = '\n' if file is None: file = sys.stdout file.write(sep.join(map(str, objects)) + end) if flush: file.flush() 函数定义
从上面的代码我们可以发现,python3.x的print 函数实现了print语句的所有特性。
上面就是我从别人的博客和老师讲的内容中得出的一些启发,也算是学习笔记吧,都是总结了老师讲的内容,写到这里主要是巩固一些基础知识