python中级之字符编码
小引
字符编码(Character Encoding)是计算机显示文本的基础,是每一位 IT 从业者必知的计算机基础知识点,如同数值在计算中如何存储表示,那么基础,那么重要。
参考笔记
字符编码笔记:ASCII,Unicode 和 UTF-8 - 阮一峰的网络日志 (ruanyifeng.com)
各种编码UNICODE、UTF-8、ANSI、ASCII、GB2312、GBK详解-CSDN博客
闲谈字符和字符集以及编码(下)_闲谈字符和字符集以及编码(上)-CSDN博客
字节那些事儿_一个地址+4-CSDN博客
彻底搞懂字符编码(unicode,mbcs,utf-8,utf-16,utf-32,big endian,little endian...)-CSDN博客
字符编码储备知识
三大核心硬件
所有软件都是运行硬件之上的,与运行软件相关的三大核心硬件为cpu、内存、硬盘,我们需要明确三点
#1、软件运行前,软件的代码及其相关数据都是存放于硬盘中的 #2、任何软件的启动都是将数据从硬盘中读入内存,然后cpu从内存中取出指令并执行 #3、软件运行过程中产生的数据最先都是存放于内存中的,若想永久保存软件产生的数据,则需要将数据由内存写入硬盘
文本编辑器读取文件内容的流程
#阶段1、启动一个文件编辑器(文本编辑器如nodepad++,pycharm,word) #阶段2、文件编辑器会将文件内容从硬盘读入内存 #阶段3、文本编辑器会将刚刚读入内存中的内容显示到屏幕上
python解释器执行文件的流程
以python test.py
为例,执行流程如下
#阶段1、启动python解释器,此时就相当于启动了一个文本编辑器 #阶段2、python解释器相当于文本编辑器,从硬盘上将test.py的内容读入到内存中 #阶段3、python解释器解释执行刚刚读入的内存的内容,开始识别python语法
总结
python解释器与文件本编辑的异同如下
#1、相同点:前两个阶段二者完全一致,都是将硬盘中文件的内容读入内存,详解如下 python解释器是解释执行文件内容的,因而python解释器具备读py文件的功能,这一点与文本编辑器一样 #2、不同点:在阶段3时,针对内存中读入的内容处理方式不同,详解如下 文本编辑器将文件内容读入内存后,是为了显示或者编辑,根本不去理会python的语法,而python解释器将文件内容读入内存后,可不是为了给你瞅一眼python代码写的啥,而是为了执行python代码、会识别python语法)
字符编码
定义
什么是字符编码? 人类在与计算机交互时,用的都是人类能读懂的字符,如中文字符、英文字符、日文字符等。 而计算机只能识别二进制数,详解如下
#二进制数即由0和1组成的数字,例如010010101010。计算机是基于电工作的,电的特性即高低电平,人类从逻辑层面将高电平对应为数字1,低电平对应为数字0,这直接决定了计算机可以识别的是由0和1组成的数字
毫无疑问,由人类的字符到计算机中的数字,必须经历一个过程,如下 **字符---->翻译---->数字** 翻译的过程必须参照一个特定的标准,该标准称之为字符编码表,该表上存放的就是字符与数字一一对应的关系。 字符编码中的编码指的是翻译或者转换的意思,即将人能理解的字符翻译成计算机能识别的数字
字符编码的发展史(了解)
编码和解码(需要掌握)
编码(encode)
由字符转换成内存中的unicode,以及由unicode转换成其他编码的过程,都称为编码encode
x = '上' # 在python3在'上'被存成unicode res = x.encode('utf-8') print(res, type(res)) # unicode编码成了utf-8格式,而编码的结果为bytes类型,可以当作直接当作二进制去使用 # b'\xe4\xb8\x8a' <class 'bytes'> # 只有英文字符和数字,要想编码的话,直接使用前缀b --- 字节对象没有encode方法 s = b'Dream123' print(s, type(s)) # b'Dream123' <class 'bytes'>
解码(decode)
- 由内存中的unicode转换成字符,以及由其他编码转换成unicode的过程,都称为解码decode - 在诸多文件类型中,只有文本文件的内存是由字符组成的,因而文本文件的存取也涉及到字符编码的问题
x = b'\xe4\xb8\x8a' res = x.decode('utf-8') print(res, type(res)) # 上 <class 'str'> s = b'Dream123' res = s.decode('utf-8') print(res, type(res)) # Dream123 <class 'str'>
补充:utf-8的由来
引言
-
如果保存到硬盘的是GBK格式二进制,当初用户输入的字符只能是中文或英文
-
同理如果保存到硬盘的是Shift_JIS格式二进制,当初用户输入的字符只能是日文或英文……
-
如果我们输入的字符中包含多国字符,那么该如何处理?
-
多国字符—√—>内存(unicode格式的二进制)——X—>硬盘(GBK格式的二进制)
-
多国字符—√—>内存(unicode格式的二进制)——X—>硬盘(Shift_JIS格式的二进制)
-
多国字符—√—>内存(unicode格式的二进制)——√—>硬盘(???格式的二进制)
解决办法(utf-8)
-
理论上是可以将内存中unicode格式的二进制直接存放于硬盘中的
- 但由于unicode固定使用两个字节来存储一个字符
-
如果多国字符中包含大量的英文字符时,使用unicode格式存放会额外占用一倍空间(英文字符其实只需要用一个字节存放即可)
-
然而空间占用并不是最致命的问题
- 最致命地是当我们由内存写入硬盘时会额外耗费一倍的时间
-
所以将内存中的unicode二进制写入硬盘或者基于网络传输时必须将其转换成一种精简的格式
- 这种格式即utf-8(全称Unicode Transformation Format,即unicode的转换格式)
- 我们日常使用的字符编码都是utf8编码,但是,utf系列还有utf16 utf32... utf8mb4
- utf8只能存储正常的字符,utf8mb4可以存储表情
-
多国字符—√—>内存(unicode格式的二进制)——√—>硬盘(utf-8格式的二进制)
为何在内存中不直接使用utf-8
- utf-8是针对Unicode的可变长度字符编码: - 一个英文字符占1Bytes, - 一个中文字符占3Bytes,生僻字用更多的Bytes存储 - unicode更像是一个过渡版本, - 我们新开发的软件或文件存入硬盘都采用utf-8格式 - 等过去几十年,所有老编码的文件都淘汰掉之后,会出现一个令人开心的场景 - 即硬盘里放的都是utf-8格式 - 此时unicode便可以退出历史舞台 - 内存里也改用utf-8,天下重新归于统一
字符编码的应用
学习字符编码的目的
-
学习字符编码就是为了存取字符时不发生乱码问题
-
内存中固定使用unicode无论输入任何字符都不会发生乱码
-
我们能够修改的是存/取硬盘的编码方式,如果编码设置不正确将会出现乱码问题。
乱码问题
- 乱码问题分为两种:存乱了,读乱了
存乱了
如果用户输入的内容中包含中文和日文字符,如果单纯以shift_JIS存,日文可以正常写入硬盘,而由于中文字符在shift_jis中没有找到对应关系而导致存乱了
读乱了
- 如果硬盘中的数据是shift_JIS格式存储的,采GBK格式读入内存就读乱了
总结
- 保证存的时候不乱
- 在由内存写入硬盘时,必须将编码格式设置为支持所输入字符的编码格式
- 保证存的时候不乱
- 在由硬盘读入内存时,必须采用与写入硬盘时相同的编码格式
Python解释器执行文件
Python解释器执行文件的前两个阶段
-
执行py文件的前两个阶段就是python解释器读文本文件的过程,与文本编辑读文本文件的前两个阶段没人任何区别
-
要保证读不乱码,则必须将python解释器读文件时采用的编码方式设置为文件当初写入硬盘时的编码格式
-
如果没有设置,python解释器则才用默认的编码方式,在python3中默认为utf-8,在python2中默认为ASCII
-
我们可以通过指定文件头来修改默认的编码
-
在文件首行加上
# coding: 当初文件写入硬盘时采用的编码格式 -
解释器会先用默认的编码方式读取文件的首行内容
- 由于首行是纯英文组成,而任何编码方式都可以识别英文字符。
python解释器执行文件的第三个阶段
-
设置文件头的作用是保证运行python程序的前两个阶段不乱码
- 经过前两个阶段后py文件的内容都会以unicode格式存放于内存中。
-
在经历第三个阶段时开始识别python语法
- 当遇到特定的语法name = '上'(代码本身也都全都是unicode格式存的)时
- 需要申请内存空间来存储字符串'上'
- 这就又涉及到应该以什么编码存储‘上’的问题了。
-
在Python3中
-
字符串类的值都是使用unicode格式来存储
-
由于Python2的盛行是早于unicode的
- 因此在Python2中是按照文件头指定的编码来存储字符串类型的值的(如果文件头中没有指定编码
- 那么解释器会按照它自己默认的编码方式来存储‘上’)
- 所以,这就有可能导致乱码问题
# coding:utf-8 # x的值为untf-8格式的二进制 x = '上' # 打印操作是将x的值,即utf-8格式的二进制交给终端 # 当终端收到后发现并不是unicode(只有unicode才与字符有对应关系) # 所以终端会执行操作:utf-8二进制---解码-->unicode格式的二进制 # 解码的过程终端会采用自己默认的编码 # 而在pycharm的终端默认编码为utf-8、windows下的cmd终端的默认编码为gbk # 所以该打印操作在pycharm中显示正常,而在windows下的cmd中则乱码 print(x)
# 在windows下的cmd中运行效果如下 C:\Users\Administrator>python2 E:\aaa.py 涓
- python2后推出了一种补救措施,就是在字符串类型前加u
- 则会将字符串类型强制存储unicode
- 这就与python3保持一致了
- 对于unicode格式无论丢给任何终端进行打印,都可以直接对应字符不会出现乱码问题
# coding:utf-8 x = u'上' # 即便文件头为utf-8,x的值依然存成unicode
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?