python 编码

1 什么是编码?

     人们通过显示器看到的数字符号,但是计算机是不能识别的。计算机因为电器特性,能识别高低电平。人们给高电平赋1,低电平赋0。因为计算机有了识别0、1的功能。但如何把01变成人们所看到的具体的符号和数字。这其中就涉及到编码。也就是把一串“无意义”的符号转换成人们所看到的字符(明文)的过程就叫编码。


2 编码的发展史

     最初计算机诞生时,是在美国,ASCII(American Standard Code for Information Interchange,美国标准信息交换代码)是基于拉丁字母的一套电脑编码系统。起初用7位来表示。但考虑到扩充,多用了1位。拉美的一些国家,用127以后的来扩展自己的编码。也就有了现在的扩展ascii表。

     但当计算机到达中国时,发现汉字太多,1个字节装不下那么多汉字。但为了能兼容美国的原ascii编码,于是多取了1位,用两位来编码汉字。规定两位都大于127,就认为这两位编码一个汉字。于是gb2312(1980年)诞生了一共收录了7445个字符,包括6763个汉字和682个其它符号。

     后来发现gb2312支持的汉字编码字符太少了。于是规定连续的两个字节,只需第一个大于127,就认为它编码一个汉字。于是,gbk1.0(1995年)诞生了。收录了21886个符号,它分为汉字区和图形符号区。汉字区包括21003个字符。

     2000年的 GB18030是取代GBK1.0的正式国家标准。该标准收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。现在的PC平台必须支持GB18030,对嵌入式产品暂不作要求。所以手机、MP3一般只支持GB2312。但windows默认支持的是gbk编码。

    由于每个国家都有自己的编码,给国际贸易带来了诸多不便。于是,联合国发布了一套统一的编码unicode(万国码)。用两个字节表示一个字符,总共有65535个不同的字符。
     unicode虽然迎合了大多数国家的需要,但却对原本使用ascii编码的国家(如美国、拉美等)并不友好。原本他们使用1个字节可以存储的,现在却需要多付出一倍(2个字节)的代价(传输带宽、本地存储)。于是推出了可变长的utf-8编码,美国用1个字节,欧洲用2个字节,中国用3个字节。
     使用utf-8的好处是,虽然在内存里面是unicode编码,但当数据保存到磁盘或网络传输时,要比unicode节省很多空间。
最后概括:unicode是内存编码方案,而utf-8是存储到磁盘和网络传输的编码方案。


# 3 编码和解码 编码:将字符转字节的过程。 解码:字节转字符的过程。
# 4 在python2和python3中 `repr()可以数据转换成利于解释器读取的字符串形式` `type()查看是什么对象类型的`
  • 先看python2:
# -*- coding:utf-8 -*-
s="中国"
print(s)   #中国
print(type(s))  #<type 'str'>
print(repr(s))  #'xe4xb8xadxe5x9bxbd'
print(s.decode("utf-8"))   #中国
print(type(s.decode("utf-8")))   #<type 'unicode'>
print(repr(s.decode("utf-8")))   #u'u4e2du56fd'
s1=u"中国"
print(s1)    #中国
print(type(s1)) #<type 'unicode'>
print(repr(s1))   #u'u4e2du56fd'
s2=b"中国"
print(s2)     #中国
print(type(s2))   #<type 'str'>
print(repr(s2))   #'xe4xb8xadxe5x9bxbd'

     在python2中,变量s赋的一个中文字符串,而python默认的是ascii,所有需要手动添加“# -- coding:utf-8 --”,让他以utf-8格式来解释字符串。type(s)返回的是“str”,但repr(s)返回的是bytes数据类型。以utf-8解码s后,type(s)返回的是“unicode”,repr(s)返回的是unicode数据类型。和s1一样。
     为什么print(s1),也是“中国”?这里的s1的数据类型是unicode类型的,会被pycharm自动编码成pycharm设置的编码类型。所以utf-8和unicode都能正常显示。
     而s2,本身是bytes,会被解释器以手动添加的utf-8格式来解释。所以能正常显示。
总结:在python2,str对象存bytes数据类型的,unicode对象存unicode数据类型的。

  • Python3:
# -*- coding:utf-8 -*-
#s1=b"中国"    #SyntaxError: bytes can only contain ASCII literal characters.
s1="中国"
s2=u"中国"
# print(s1.decode("utf-8"))   #报错
# print(type(s1.decode("utf-8")))    ##报错
# print(repr(s1.decode("utf-8")))   ##报错
print(s1)            #中国
print(type(s1))         #<class 'str'>
print(repr(s1))       #'中国'
print(s2)           #中国
print(type(s2))    #<class 'str'>
print(repr(s2))          #'中国'
print(s2.encode("utf-8"))    #b'xe4xb8xadxe5x9bxbd'
print(type(s2.encode("utf-8")))   #<class 'bytes'>
print(repr(s2.encode("utf-8"))) #b'xe4xb8xadxe5x9bxbd'

在python3中,最大的改变是把str和bytes分开。
     s2本身是unicode数据类型的,所以能真正常显示。但我们会发现s2调用encode(),编码成utf-8后,不能正常显示了。也就是说在python3中,只能正常显示unicode,其他的类型都是bytes。同时unicode的repr()能正常打印。
总结:在python3中,str对象存unicode数据类型的,bytes对象存bytes数据类型的。

ps:在计算机里,unicode是最基层的编码格式,其他编码格式(如ascii、utf-8、gbk等)的数据通过decode()转换成unicode类型的数据,unicode类型的数据通过encode()转换成其他编码格式的数据。


# 5 文件在磁盘的编码      windows记事本是如何保存txt文件到本地又是如何从本地把txt读入内存的并正常显示的?      作为一个程序,记事本不能直接操作硬件,它需要对系统发起系统调用请求,windows才会将磁盘中的txt文件读到内存。当记事本本身作为一款程序加载在内存中时,实际上就是以unicode编码读入内存的,所以当我们在记事本中写入一串文字,此时这串文字此时也在内存中,并以unicode编码的。当我们点击保存时,记事本会以默认的编码格式,如默认utf-8,先将这串文字编码成utf-8二进制格式再保存到磁盘。      当我们再打开这个文件时,软件又默默地给我们做了解码的工作,将数据再解码成unicode,然后就可以呈现明文给用户了!所以,unicode是离用户更近的数据,bytes是离计算机更近的数据。 补充:unicode和utf-8其实都是一种二进制编码方式。
# 6 编码常见的问题 python2在cmd下的乱码。 用notepad++新建一个hello.py,并写入 ```python print("中国") ``` 以utf-8无bom格式保存到磁盘中。 在cmd下运行 ```python python27 hello.py ``` 结果: ```python File "hello.py", line 2 SyntaxError: Non-ASCII character 'xe4' in file hello.py on line 2, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details ``` 提示无ascii字符。为什么是这样的错误? 此时是用python27解释器去执行hello.py,和cmd没什么关系。python2m默认的编码是ascii。而"中国"这两个字符在ascii表没有对应的字符编码。所以提示这样的错误。

在print前面加入一行:

# -*- coding:utf-8 -*-

手动声明编码格式,不再采用python2默认的ascii编码。
结果:

涓�浗

(中间这个字显示不出来,是因为为知笔记的问题。在cmd显示的是一个口和恶组成的字)
为什么现在能显示,但现实“乱码”?
严格说,这种不叫“乱码”,应该叫“串码”。因为声明以utf-8的编码格式。所以程序执行前,python2解释器从磁盘中将hello.py代码读入内存是先以utf-8解码成unicode读入内存的。由于str在python2中是bytes数据类型,代码在内存中运行时的编码方式就是utf-8。但cmd默认以gbk编码,所以最后读出来3个字。

将内容改为如下,并以utf-8无bom格式保存:

# -*- coding:utf-8 -*-
print("中国".decode("utf-8"))

结果:

中国

友情提
示:http://www.cnblogs.com/yuanchenqi/articles/5956943.html

原文地址:https://www.cnblogs.com/yangzhenwei123/p/6759181.html