导语
经常看到有人问关于python编码的问题,但网上关于python编码的文章大多含糊其辞,有用而无大用,于是想着以个人粗鄙之见聊一聊关于python编码的问题。
测试系统
Windows版本:
Linux版本:
进入正题
说明:
本文所涉及的所有内容均基于python3。
首先,我们来看看下面这段代码:
在Windows系统下的运行结果为:
注1:
cp936即gbk。
在Linux系统下的运行结果为:
为什么系统默认编码和本地默认编码不一样呢(sys:系统,locale:本地)?
这里我们需要搞清楚系统默认编码和本地默认编码的区别:
① 系统默认编码
这里的系统不是操作系统,而是python系统,可以认为是python的编译器,因此系统默认编码即python编译器的默认编码。
② 本地默认编码
本地指的才是操作系统,因此本地默认编码即操作系统的默认编码。
显然,python编译器的默认编码在不同的操作系统中保持一致,操作系统的默认编码随操作系统的不同而发生了改变。
注2:
python2和python3编译器的默认编码是不同的,分别是ascii和utf-8。
那么他们各自有什么用呢?
① 系统默认编码
当python的编译器读取.py文件时,若无编码声明,则使用系统默认编码来解码.py文件。
注3:
编码声明告诉了python编译器以什么格式的编码来解码.py文件,即它不会改变系统默认编码和本地默认编码,也不是用于声明当前代码文件的编码格式的,而是声明当前代码文件的解码方式。换句话说,代码文件的编码格式取决于你使用的编辑器,而如何解码该文件取决于文件头处的编码声明。
一般地,编码格式应当与解码格式一致,即编辑器的编码格式与编码声明应当一致,但保持一致并不代表含义相同。
② 本地默认编码
对于open()函数,若不声明编码,则自动使用本地默认编码:
更进一步。
接下来我们来看一段代码及其运行结果,然后结合上面的铺垫来解释一下为什么会有这样的运行结果:
注4:
TIS-620为泰文编码。
Windows系统下运行结果:
Linux系统下运行结果:
这示例代码也太逗了吧,还报错?开个玩笑,显然,最受人瞩目的应当是代码报错了吧,乱码怎么也比报错强吧?OK,那我们就先来解释一下代码报错的原因吧:
首先,我用代码编辑器写好了上图中的代码并保存,其中代码编辑器使用的编码格式为utf-8,上图为证:
即代码以utf-8的编码格式保存在代码文件中。现在运行该代码文件,根据编码声明,编译器使用gbk来解码该.py文件,根据终端的打印结果可知:
现在我们需要将test_str写入磁盘,根据错误提示,我们发现以utf-8和gbk编码格式将其写入磁盘时,并没有报错,但以泰文编码格式将其写入磁盘时,却发生了报错。
Why?因为泰文里没有中文字符啊!所以编码到中文字符时,就提示编码失败了!
注5:
position 7代表第八个字符。
现在我们再来看看乱码问题!为什么以utf-8编码格式将变量写入磁盘时发生了乱码,而以gbk编码格式将变量写入磁盘时却没有发生乱码呢?其中究竟发生了什么事情?
① 以gbk编码格式将变量写入磁盘
编解码过程如下:
即编译器使用gbk来解码utf-8编码的.py文件之后,又利用gbk编码格式将获得的变量写入的到磁盘文件中,之后打开该磁盘文件,代码编辑器用utf-8解码该.py文件后显示文件内容。显然,步骤三是步骤二的逆过程,步骤四是步骤一的逆过程,因此,最终结果是不会发生乱码的。
② 以utf-8编码格式将变量写入磁盘
显然,此处步骤四是步骤三的逆过程,最终的结果显示乱码也就在意料之中了。
写在最后。
① 为什么经常看到utf-8解码报错?
utf-8的定义十分严格,英文字符占一个字节(高位必须为0),阿拉伯文占两个字节,中文以及日文占三个字节(第一个字节的高位必须是1110)。而gbk则比较死板,所有字符都占两个字节。
② Unicode是啥?
Unicode只是一个符号集,一个字符对应一个数字(或者说是一个ID);utf-8则是一种编码规则,用于实现Unicode的传输和存储。
想进一步了解两者区别的话,请参考:
https://www.zhihu.com/question/23374078
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
That's all.
更多
以上内容仅代表个人理解。
如有错误,还望指正。
○
○
Charles的皮卡丘
Pikachu~
领取专属 10元无门槛券
私享最新 技术干货