Python的解码和编码

使用Python语言做网络爬虫或者写自动化脚本时,总会遇到“中文乱码”的问题,很是头疼。很多“中文乱码”的问题是跟Python的解码/编码有关,所以今天和大家说说Python的解码/编码(以Python2.7为例)。

1.什么是Python解码/编码?

Python里面的解码和编码也就是unicode和str这两种形式的相互转化。解码就是str -> unicode,相反的,编码是unicode -> str。

总的来说就是:unicode是Python解释器的内码,所有代码文件在导入并执行时,Python解释器会先将字符串使用你指定的编码形式解码成unicode,然后再进行各种操作。不管是对字符串的操作,还是正则表达式,还是读写文件等等最好都通过unicode来进行。

Python解释器在导入Python代码文件并执行时,会先查看文件头有没有编码声明(例如# -*- coding: utf-8 -*-等)。如果发现声明,如# -*-coding: utf-8 -*-,会将文件中的字符串从utf-8先解释成unicode的形式;如果文件头没有编码声明,则会以默认的ASCII来解释成unicode的形式。

2.解码函数decode()和编码函数encode()

在Python中,解码函数是decode(),编码函数是encode()。

﹒decode()的作用是将其他编码的字符串转换成unicode 格式,例如:name.decode(“utf-8”),表示将utf-8编码的字符串name转换成unicode

﹒encode()的作用是将unicode编码转换成其他编码的字符串,例如:

name.encode(“GB2312”),表示将GB2312编码的字符串name转换成GB2312

当代码中同时有编码声明(例如# -*- coding: utf-8 -*-等)和编码函数encode(‘gbk’),Python在执行时会优先选择真实编码gbk。当存在encode(‘gbk’)时,即便在开头申明了#-*- coding: utf-8 -*-,没有指定解码方式,程序是会报错的。

解决方案:在中文“哈哈”前加上字符“u”,直接使字符是unicode类型,不用再将“哈哈”去解码操作。

注意:上图中的 '\xb9\xfe\xb9\xfe'是“哈哈”的gbk编码;'\xe5\x93\x88\xe5\x93\x88'是“哈哈”的utf-8编码。上图说明,当存在encode(‘gbk’)时,即便在开头申明了#-*- coding: utf-8 -*-,在执行时会优先选择encode()函数中的gbk编码方式。

需要注意的一点是,假设stra=‘哈哈’,如果我们调用stra.encode(),这里涉及到一个隐士的类型转化,会先将stra转化成unicode,才能进行编码,这也是不太容易理解的地方。而在中文前添加“u”字符,就使得stra转化成unicode这一步略去。

3.Python解码

解码是Python自动进行的,我们在程序开头没有编码声明(如:#-*-coding:utf-8-*-),也没有指明解码方式,Python就会使用sys.defaultencoding指明的方式来解码。很多情况下sys.defaultencoding是ASCII。

4.Python编码

Python默认采用ASCII编码,而ASCII编码不能用来编码中文字符。举个简单的例子:

如下图,运行脚本时会有提示。因为Python编码默认是ASCII编码,不支持中文。

解决方案1:在文件开头输入支持中文的编码方式:# -*- coding: gbk -*-。

解决方案2:Python2.x默认是不支持中文的,我们在程序的开头加上#-*-coding:utf-8-*-,并在中文前加上“u”字符,也可以解决这个问题。这里的“u”表示将后面跟的字符串以unicode格式存储,然后Python会根据程序第一行的utf-8编码识别代码中的中文“你好”,然后转换成unicode对象(重申一下:中文前加“u”,直接免去“将字符串解码成unicode”这一步的操作哦)。

补充一点:如果在中文前没有添加“u”,仅仅在程序的开头加上#-*-coding:utf-8-*-,屏幕上打印出的不是“你好”,如下图。这是由于Python编码与控制台编码的不一致造成的。Windows下控制台中的编码使用的是gbk,而在代码中使用的utf-8,Python按照utf-8编码打印到gbk编码的控制台下自然就会不一致而不能打印出正确的汉字。

总之,在Python2.x版本中使用中文,最好在程序开头添加一行声明文件编码的注释:#-*-coding:utf-8-*-,然后在中文前添加“u”字符。可以不使用解码、编码函数,就尽量别使用(真的会绕晕的,哈哈……)。

原创文章,仅代表非比君个人观点,说的不一定是对的,欢迎大家指正。

用微信添加 非比测试 公众号即可订阅。转载请保留作者、公共账号信息,内容必须与本文保持严格一致,不得修改/替换/增减本文包含的任何文字,不得擅自增加小标题、引语、摘要等。本公众号一切内容禁止摘编、衍生及演绎。

本文来自企鹅号 - 非比测试媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Hongten

python开发_counter()

804
来自专栏Hongten

python开发_re和counter

=============================================

732
来自专栏白驹过隙

Redis - set类型操作

38213
来自专栏nnngu

015 反射中的 Class.forName() 与 ClassLoader.loadClass() 的区别

Class.forName() 与 ClassLoader.loadClass() 大家都知道是反射用来构造类的方法,但是他们的用法还是有一定区别的。 在讲区别...

2633
来自专栏申龙斌的程序人生

零基础学编程007:FOR循环

在上篇文章《赋值语句》之后,已经可以输出这个枯燥的《复利数据表》的任意一行数据了,例如用这两条语句: i = 100 print( "(1+0.01) ^", ...

3037
来自专栏Python疯子

TebsorFlow基本语法

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invi...

1382
来自专栏coding for love

JS入门难点解析5-变量对象

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

1174
来自专栏用户3030674的专栏

java线程控制安全

在线程运行的时候,有时会出现线程安全问题 例如:买票程序,有可能会出现不同窗口买同一张编号的票

780
来自专栏L宝宝聊IT

Shell脚本应用(if语句的结构)

1445
来自专栏和蔼的张星的图像处理专栏

547. 两数组的交

样例 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2].要求去重,这样还是稍微有点难度。

892

扫码关注云+社区

领取腾讯云代金券