Python字符编码

字符编码

计算机只认识数字,咱们平时在使用计算机时,用的都是人类能读懂的字符(用高级语言编程的结果也无非是在文件内写了一堆字符),如何能让计算机读懂人类的字符?必须通过一个过程: 字符--------(翻译过程)------->数字 这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准称之为字符编码node

1、存取文件的原理(nodepad++,pycharm,word)

  • a、打开编辑器就打开了启动了一个进程,是在内存中的,因此,用编辑器编写的内容也都是存放与内存中的,断电后数据丢失
  • b、要想永久保存,须要点击保存按钮:编辑器把内存的数据刷到了硬盘上。
  • c、在咱们编写一个py文件(没有执行),跟编写其余文件没有任何区别,都只是在编写一堆字符而已。

2、编码发展

  • 阶段1:现代计算机起源于美国,最先诞生也是基于英文考虑的ASCII,ASCII:用1个字节Bytes(8位二进制)表明一个字符
  • 阶段2:为了知足中文和英文,中国人定制了GBK, GBK:2Bytes表明一个中文字符,1Bytes表示一个英文字符
  • 阶段3:各国有各国的标准,出现冲突,unicode出现了,可以兼容万国字符。 unicode(定长):经常使用2个字节(16位二进制)表明一个字符,生僻字须要用4个字节
  • 阶段4:对于通篇都是英文的文原本说,unicode的式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的)因而产生了UTF-8(可变长,全称Unicode Transformation Format)UTF-8:对英文字符只用1Bytes表示,对中文字符用3Bytes,对其余生僻字用更多的Bytes去存。

3、乱码来源

  • 乱码1:存文件时就已经乱码
  • 存文件时,因为文件内有各个国家的文字,咱们单以shiftjis去存, 本质上其余国家的文字在shiftjis中没有找到对应关系,不能存而硬存,确定是乱存了,即存文件阶段就已经发生乱码,而当咱们用shiftjis打开文件时,日文能够正常显示,而中文则乱码了。
  • 乱码2:存文件时不乱码而读文件时乱码【按照什么标准编码的,就要按照什么标准解码】
  • 存文件时用utf-8编码,保证兼容万国,不会乱码,而读文件时选择了错误的解码方式,好比gbk,则在读阶段发生乱码,读阶段发生乱码是能够解决的,选对正确的解码方式就ok了,

4、特别说明

  • 指定头信息#-*-coding:utf-8-*- python解释器编码就是头信息编码, 没有指定头信息,那就使用默认的python2中默认使用ascii,python3中默认使用utf-8。
  • 在python2中有两种字符串类型str(编码成文件头指定的编码格式)和unicode 在python3 中也有两种字符串类型str(直接编码成unicode)和bytes python2中的str类型就是python3的bytes类型
  • 特别说明print时,open时,没指定编码格式就使用终端的编码格式。
  • sys.stdout.encoding,默认就是locale的编码,print会用sys.stdout.encoding去encode()成字节流,交给terminal显示。因此locale须要与terminal一致,才能正确print打印出中文。
  • 浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器
  • 若是服务端encode的编码格式是utf-8, 客户端内存中收到的也是utf-8编码的结果。
  • *****内存中统一采用unicode,浪费空间来换取能够转换成任意编码(不乱码),硬盘能够采用各类编码,如utf-8,保证存放于硬盘或者基于网络传输的数据量很小,提升传输效率与稳定性。*****
  • ***在存入磁盘时,须要将unicode转成一种更为精准的格式,utf-8****
  • ***在读入内存时,须要将utf-8转成unicode****

5、python解释器执行py文件的3个阶段

  • 阶段1:启动python解释器至关于启动了一个文本编辑器
  • 阶段2:从硬盘读取test.py文件内容到内存。【此时,python解释器会读取test.py的头信息#-*-coding:utf-8-*-,来决定以什么编码格式读入到内存,能够用sys.getdefaultencoding()查看,若是没有指定头信息#-*-coding:utf-8-*-,那就使用python解释器默认的编码,python2中默认使用ascii,python3中默认使用utf-8。】
  • 阶段3:解释执行阶段。【在该阶段,才会识别python的语法,执行文件内代码,当执行到name="tom"时,会开辟内存空间存放字符串"tom"。】
  • python解释器比文本编辑器多了阶段3

细说阶段3

  • 在程序执行以前,内存中都是unicode
  • 程序在执行过程当中,会申请内存(与程序代码所存在的内存是俩个空间)用来存放python的数据类型的值,好比x="tom",会被python解释器识别为字符串,会申请内存空间来存放字符串类型的值,至于该字符串类型的值被识别成何种编码存放,这就与python解释器有关了,而python2与python3的字符串类型又有所不一样。  
  • 在python2中有两种字符串类型str(编码成文件头指定的编码格式)和unicode
  • 在python3中也有两种字符串类型str(直接是unicode)和bytes (也就是python2中的str)
  • 字节字符串和字符字符串
  • (内存)unicode----->encode-------->utf-8(硬盘)
  • (硬盘)utf-8----->decode-------->unicode(内存)

6、总结

  • 字符按照什么标准而编码的,就要按照什么标准解码
  • 在内存中写的全部字符,一视同仁,都是unicode编码,好比咱们打开编辑器,输入一个“你”,咱们并不能说“你”就是一个汉字,此时它仅仅只是一个符号,该符号可能不少国家都在使用,根据咱们使用的输入法不一样这个字的样式可能也不太同样。只有在咱们往硬盘保存或者基于网络传输时,才能肯定”你“究竟是一个汉字,仍是一个日本字,这就是unicode转换成其余编码格式的过程了
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
#将bytes转换为str
name_b = b 'tom'
name_s1 = name_b.decode( 'utf-8' )
name_s2 = str (name_b,encoding = 'utf-8' )
print (name_b, type (name_b)) #b'tom' <class 'bytes'>
print (name_s1, type (name_s1)) #tom <class 'str'>
print (name_s2, type (name_s2)) #tom <class 'str'>
 
#将str转换为bytes
gender = 'male'
gender_b1 = gender.encode( 'utf-8' )
gender_b2 = bytes(gender,encoding = 'utf-8' )
print (gender, type (gender)) #male <class 'str'>
print (gender_b1, type (gender_b1)) #b'male' <class 'bytes'>
print (gender_b2, type (gender_b2)) #b'male' <class 'bytes'>