Python——字符编码
转自知乎专栏:https://zhuanlan.zhihu.com/p/108805502
歪比歪比总结
- 总结1:用什么编码就用什么解码(用什么编码存的就用什么编码取)
- 总结2:python3的str类型无论如何都不会乱码默认保存unicode格式,python2中需要加上u即
x=u'上'
来保证str类型不乱码 - 总结3:保证运行python程序前两个阶段不乱码的核心法则:
'''
指定文件头
# coding:文件当初存入硬盘时所采用的编码格式
'''
- 总结4:python解释器默认读文件的编码
# python3默认:utf-8
# python2默认:ASCII
一、知识储备
1.1 三大核心硬件
-
1、软件运行前,软件的代码及其相关数据都是存放于硬盘中的
-
2、任何软件的启动都是将数据从硬盘中读入内存,然后cpu从内存中取出指令并执行
-
3、软件运行过程中产生的数据最先都是存放于内存中的,若想永久保存软件产生的数据,则需要将数据由内存写入硬盘
1.2 文本编辑器读取文件内容的流程
- 第一步:启动文本编辑器
- 第二步:文本编辑器将文件内容从硬盘读入内存
- 第三步:文本编辑器将读入内存的文件内容显示在屏幕上
1.3 python解释器执行文件的流程
- 第一步:启动python解释器
- 第二步:python解释器将文件内容从硬盘读入内存(与文本编辑器相同,文件内容只是普通内容)
- 第三步:python解释器解释执行读入内存的文件内容,并开始识别python语法
1.4 总结
-
两者在启动以及将文件内容从硬盘读入内存的操作完全一致
-
文本编辑器将文件内容读入内存后,是为了显示或者编辑,不会识别python的语法,而python解释器将文件内容读入内存后,会识别并执行python语法)
二、字符编码介绍
2.1 什么是字符编码
-
人类在与计算机交互时,用的都是人类能读懂的字符,如中文字符、英文字符、日文字符等
而计算机只能识别二进制数。因此需要进行一个转换(翻译)过程
-
转换的过程必须有一个特定的参照标准,该标准称之为字符编码表,该表上存放的就是字符与数字一一对应的关系。
-
字符编码中的编码指的是翻译或者转换的意思,即将人能理解的字符翻译成计算机能识别的数字
2.2 字符编码得发展史(了解)
-
老祖宗:ASCII表
-
各自安家立业:美国:ASCII、中国:GBK、日本:Shift_JIS、韩国:EUC-KR
-
统一:Unicode
# Unicode ''' 1、兼容各国字符、与各国字符都有对应关系 2、采用16位(16bit=2Bytes)二进制数对应一个中文字符串,个别生僻会采用4Bytes、8Bytes ''' ''' # 英文字符可以被ASCII识别 英文字符--->unciode格式的数字--->ASCII格式的数字 # 中文字符、英文字符可以被GBK识别 中文字符、英文字符--->unicode格式的数字--->gbk格式的数字 # 日文字符、英文字符可以被shift-JIS识别 日文字符、英文字符--->unicode格式的数字--->shift-JIS格式的数字 '''
2.3 编码与解码
- 由字符转换成内存中的Unicode,以及由Unicode转换成其他编码的过程,都称为编码encode
- 由内存中的Unicode转换成字符,以及由其他编码转换成Unicode的过程,都称为解码decode
2.4 utf-8的由来
-
理论上可与将内存中的Unicode格式的二进制直接存放到硬盘中,但是由于Unicode固定使用两个字节来存储一个字符,这就使得如果我们输入的字符中包含大量的英文字符时,Unicode格式就会额外占用一部分空间,最为致命的是当我们由内存写入硬盘时会额外消耗一倍的时间也就是IO延迟时间,针对这种情况,也就产生了基于Unicode的一种精简格式——utf-8,它是Unicode的转换格式
# 多国字符—√—》内存(unicode格式的二进制)——√—》硬盘(utf-8格式的二进制)
-
为什么内存不直接使用utf-8?
# 这就相当于问你为什么不直接出python3而要先出python2一个道理 ''' utf-8是针对Unicode的可变长度字符编码: 一个英文字符占1Bytes, 一个中文字符占3Bytes, 生僻字用更多的Bytes存储 Unicode就相当于是一个过渡版本, 我们新开发的软件或文件存入硬盘都采用utf-8格式, 等过去几十年,所有老编码的文件都淘汰掉之后,会出现一个令人开心的场景, 即硬盘里放的都是utf-8格式,此时unicode便可以退出历史舞台,内存里也改用utf-8 '''
三、字符编码的应用
3.1 文本编辑器nodpad++存取文本文件
- 文本编辑器存取的都是文本文件,而文本文件中包含的内容全为字符,所以存取文本文件都涉及到字符编码的问题。
3.2 python解释器执行文件的前两个阶段
-
与文本编辑器没有任何区别,要保证读不乱码,则必须将python解释器读文件时采用的编码方式设置为文件当初写入硬盘时的编码格式,如果没有设置,python解释器则才用默认的编码方式,在python3中默认为utf-8,在python2中默认为ASCII,我们可以通过指定文件头来修改默认的编码
-
在文件首行写入包含#号在内的以下内容
# coding: 当初文件写入硬盘时采用的编码格式 ''' 解释器会先用默认的编码方式读取文件的首行内容, 由于首行是纯英文组成,而任何编码方式都可以识别英文字符。 '''
3.3 python解释器执行文件的第三个阶段
'''
设置文件头的作用是保证运行python程序的前两个阶段不乱码,
经过前两个阶段后py文件的内容都会以unicode格式存放于内存中。
在经历第三个阶段时开始识别python语法,
当遇到特定的语法name = '上'(代码本身也都全都是unicode格式存的)时,
需要申请内存空间来存储字符串'上',这就又涉及到应该以什么编码存储‘上’的问题了。
'''
-
在Python3中,字符串类的值都是使用unicode格式来存储
-
Python2中是按照文件头指定的编码来存储字符串类型的值的
''' 由于Python2的盛行是早于unicode的,因此在Python2中是按照文件头指定的编码来存储字符串类型的值的 如果文件头中没有指定编码,那么解释器会按照它自己默认的编码方式来存储‘上’, 所以,这就有可能导致乱码问题 # coding:utf-8 x = '上' # x的值为untf-8格式的二进制 print(x) # 打印操作是将x的值,即utf-8格式的二进制交给终端, 当终端收到后发现并不是unicode(只有unicode才与字符有对应关系), 所以终端会执行操作:utf-8二进制---解码-->unicode格式的二进制, 解码的过程终端会采用自己默认的编码,而在pycharm的终端默认编码为utf-8、 windows下的cmd终端的默认编码为gbk, 所以该打印操作在pycharm中显示正常,而在windows下的cmd中则乱码 ''' ''' python2后推出了一种补救措施,就是在字符串类型前加u, 则会将字符串类型强制存储unicode,这就与python3保持一致了, 对于unicode格式无论丢给任何终端进行打印,都可以直接对应字符不会出现乱码问题 ''' # coding:utf-8 x = u'上' # 即便文件头为utf-8,x的值依然存成unicode
3.4 字符串encode编码与decode解码的使用
# 1、unicode格式------编码encode-------->其它编码格式
>>> x='上' # 在python3在'上'被存成unicode
>>> res=x.encode('utf-8')
>>> res,type(res) # unicode编码成了utf-8格式,而编码的结果为bytes类型,可以当作直接当作二进制去使用
(b'\xe4\xb8\x8a', <class 'bytes'>)
# 2、其它编码格式------解码decode-------->unicode格式
>>> res.decode('utf-8')
'上'
结论
- 用什么编码存的,必须用什么编码读
'''
1、内存固定使用unicode,我们可以改变的是存入硬盘采用格式
英文+汉字-》unicode-》gbk
英文+日文-》unicode-》shift-jis
万国字符》-unicode-》utf-8
2、文本文件存取乱码问题
存乱了:解决方法是,编码格式应该设置成支持文件内字符串的格式
取乱了:解决方法是,文件是以什么编码格式存如硬盘的,就应该以什么编码格式读入内存
3、python3默认:utf-8
python2默认:ASCII
4、保证python程序前两个阶段不乱码的核心法则:
指定文件头修改默认编码:
在py文件的首行写:
# coding:当初文本编辑器所存的编码格式
5、python3的str类型默认保存为unicode格式,无论如何都不会乱码
保证python2的str类型不乱码
x='上' # 字符串会按照文件头指定的编码格式存入
x=u'上' # 强制存称unicode
'''