python - 字符编码篇

本章内容

  1. 什么是字符编码?
  2. python默认编码
  3. decode(解码)和encode(编码)

前言

  对于字符编码的问题,在学习python的过程中,很多新手都为之疯狂,本人也是其中之一,所以就来怼这个问题了。

一、什么是字符编码

  首先我们得知道,计算机中的所有数据,不管是文字、图片、视频、还是音频文件,本质上最终都是按照二进制存储的(就是一堆只有0、1的数字),并且计算机是只认识数字的,它并不认识你是 "A" 它是 "B" 。到这里需要先说一下,计算机的母语就是英语嘛,所以刚开始也就只是用的英语啦。我们还知道1 bytes = 8 bit ,也就是说一个字节等于8位,8位可以表达多少种不同的情况?每一位可以为0或1,那么8位则是2**8(2的8次方啊),也就是256种情况。然后呢计算机初期也只在美国使用,他们把数字、字母(包括大小写)、标点符号、空格这些基本要用的都加起来也只有127个,所以256完完全全够他们用了。于是他们用一个字节、用多种组合来存储英语的文字了。这样计算机认识这个数字的情况就相当于认识了这些字符,于是计算机就支持了英语这一门语言了。接下来进入正题:

  字符编码:(英语:Character encoding)也称字集码,是把字符集中的字符编码为指定集合中某一对象(例如:比特模式、自然数序列、8位组或者电脉冲),以便文本在计算机中存储和通过通信网络的传递。目的就是为了让计算机能 "认识" 字符。

  ASCII:上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码,一直沿用至今。其实就是开头讲的东西,应该不难理解。ASCII码使用7位2进制数表示一个字符,7位2进制数可以表示出2的7次方个字符,共128个字符。

  随着计算机的大量使用,仅仅是英文字符已经不能满足各个国家的需求了,于是各国纷纷开始对ASCII码后面的编码进行抢占啊,哈哈。然后呢就出现了各种各样的编码。详细的编码发展历史见本节尾部。

  ANSI:一种字符代码,为使计算机支持更多语言,通常使用 0x00~0x7f 范围的1 个字节来表示 1 个英文字符,即ASCII编码(只用了7位)。超出此范围的使用0x80~0xFFFF来编码,即扩展的ASCII编码(用了8位)。在 ASCII 范围内它们应该是和 ASCII 一致的。Windows里的 ANSI 其实是Windows code pages,简体中文编码GBK,实际上它是 ANSI 的一个代码页 936 。

  注:128位到255的字符集对应拉丁文。一个字节就满了。

  GB2312:从上面我们知道了,计算机已经可以 "认识" 英文,但是不认识中文啊,而且一个字节也用完了,那怎么办?于是牛逼的中国人,重新写了一张表,把第8位对应的拉丁文全给删了,哈哈,然后规定一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时就表示一个汉字,于是6000多个汉字就硬生生给造出来了。前面的一个字节(高字节),从0xA1 用高 0xF7,后面一个字节(低字节),从0xA1到0xFE。GB2312其实就是对ASCII 的中文扩展。当然6000多个汉字是肯定不能满足中文需求的,所有后续又有GB18030和GBK,这个就自己去了解吧。

  UNICODE:由于各个国家都搞出了自己的编码标准,并且互相又不支持,所以这就造成了很多问题。于是国际标准化组织就搞出了个万国码--UNICODE。UNICODE规定用两个字节来表示一个字符,总共可以组合出65535种不同的字符,这已经足以解决我们编码与编码之间的支持问题了。

  UTF-8:UNICODE是支持UTF-8的,为什么要重新搞个UTF-8?因为UNICODE所有字符都是占2个字节,这样就使本来1个字节就能搞定的东西,非得用2个存储,这不是浪费内存吗?并且我们的程序中英文会远多余中文,所以位了节省内存,就搞出了UTF-8。UTF-8规定,英文只用一个字节,中文用3个字节。

  UTF-8版本虽然具有良好的国际兼容性,但中文需要比GBK/BIG5版本多占用50%的数据库存储空间,因此并非推荐使用,仅供对国际兼容性有特殊要求的用户使用。简单地说:对于中文较多的网站,适宜用GBK编码节省数据库空间。对于英文较多的网站,适宜用UTF-8节省数据库空间。

  以上就是基本的介绍了,详细发展历史--->>字符编码发展历史

二、Python默认的编码

  首先我们对操作系统的默认编码做下基本的了解。windows中文环境下cmd的默认编码是 GBK ,我们可以在cmd下输入chcp命令(如下图),返回结果:活动代码页:936(936代表的便是GBK);Linux下的terminal默认编码为 UTF-8

  在Python中,当源代码读取进行语法校验时,会将源代码中的字符串从声明的编码转换成 Unicode 类型,等到语法校验通过后,再将这些字符换回初始的编码。

  • 在python 2.x 环境下

  python2.x 默认编码为ASCII ,可以通过以下方式可以检测:

1 import sys
2 sys.getdefaultencoding()

  不过你不要天真的以为你指定编码为UTF-8就一定能输出中文了,在Windows下cmd窗口的字符编码是GBK,规定输出的字符集必须是GBK的,所以你传进去UTF-8的中文自然GBK是不兼容的,所以还是乱码。

  解决方法:

  1.

 1 # _*_ coding:utf-8 _*_
 2
 3 # 定义一个变量内容为中文,字符集为UTF-8
 4 temp = "中文"
 5
 6 # 解码,需要指定原来是什么编码
 7 temp_unicode = temp.decode("utf-8")
 8
 9 # 编码,需要指定要转换成什么编码
10 temp_gbk = temp_unicode.encode("gbk")
11
12 # 输出转换成的gbk编码
13 print(temp_gbk)

  2.

 1 # _*_ coding:utf-8 _*_
 2
 3 # 定义一个变量内容为中文,字符集为UTF-8
 4 temp = "中文"
 5
 6 # 解码,需要指定原来是什么编码
 7 temp_unicode = temp.decode("utf-8")
 8
 9 # 输出转换成的gbk编码
10 print(temp_unicode)
11 # Windows终端需要GBK,DOS自动转换成GBK
12
13 注:decode() 和 encode() 将在下一小节进行整理
  • 在python 3.x 环境下

  通过以上方法可以知道python3.x 默认编码为 UTF-8 。python 2.x 到 3.x 编码的问题有了很大的改进。2.x中编码的问题绝对会让你头疼,而3.x则轻松得多。虽然在 2.x 和 3.x 中都引入了Unicode,但是在 2.x 中的字符串有两种类型(unicode和str),默认是str类型,也就是说如果你要改变一个字符串的编码,你得先解码(decode)成unicode,然后再编码(encode)成你所要转的编码;而在 3.x 中默认就是unicode类型,例:字符串不再区分"abc"和u"abc", 字符串"abc"默认就是unicode。

  盗alex老师的一个图,下图只适用于python 2.x:

  • 再说一下Unicode

  python之所以这么受欢迎,跟它引入了Unicode有莫大的关系,因为对不同国家和地区所用的字符的友好支持。

  现在我们来考虑一下,我们上面已经说了在python2.x 环境下,默认是ASCII,那么我们写代码时出现了ASCII不支持的字符,那怎么办?我们先看一个图:

    (图片来源:http://nltk.googlecode.com/svn/trunk/doc/book/ch03.html)

  这个图我们可以看出来,所有超出ASCII范围的字符处理工作,无论是在输入之前,或者输出之后是什么编码格式,它们在python的执行内存中,都统一被解码(decode)成了Unicode格式。所以Unicode啊,这个万国码可不是闹着玩的,完全就是一个中转站,什么编码都能处理。

  注:在python2.x中可以看见 u‘abc‘ 这种前面加 u 的字符串,其实就是说它着是一个unicode类型的字符串,不过在 3  中这个方法被废弃了,因为不需要了。

三、decode() 和 encode()

  从上述两点中应该已经能知道这个东西了。

  decode(解码):清除原有编码格式,并解码成unicode。decode是将bytes类型变成str类型。所以,str类型是没有decode方法的。

   encode(编码):将unicode转成其他编码。encode是将str类型变成bytes类型。bytes类型也没有encode方法。

  在用这两个方法的时候经常会犯错,就是因为不清楚各个字符编码之间的兼容关系,以及运用对象。所以我们需要弄清楚兼容的问题,比如:UTF-8 和 GBK 都支持中文,但是就是不兼容,一个是从Unicode中提取出的扩展集,另一个则是在ASCII基础上进行重新修改的字符集。

  还有不清楚的看看以下两个例子:

 1 #-*-coding:utf-8-*-
 2 #指定编码格式
 3
 4 import sys
 5 #导入模块
 6
 7 print(sys.getdefaultencoding())
 8 #打印默认编码
 9
10 name = "里昂"
11 name_gb2312 = name.decode("utf-8").encode("gb2312")
12 #先解码成unicode(需指定原编码格式),再编码成gb2312
13
14 gb2312_to_gbk = name_gb2312.decode("gbk").encode("gbk")
15 #先解码成unicode,同上,再编码成gbk
16
17 print(name)
18 #打印名字
19
20 print(name_gb2312)
21 #打印gb2312编码下的名字
22
23 print(gb2312_to_gbk)
24 #打印gbk编码下的名字

在python 2.x 中

 1 import sys
 2 #导入模块
 3
 4 print(sys.getdefaultencoding())
 5 #打印默认编码
 6
 7 name = "里昂"
 8 #name_gb2312 = name.decode("utf-8").encode("gb2312")   py2
 9 name_gb2312 = name.encode("gb2312")
10  #py3 默认就是unicode,不用再decode
11
12 gb2312_to_unicode = name_gb2312.decode("gb2312")
13 #decode成unicode
14
15 gb2312_to_utf8 = name_gb2312.decode("gb2312").encode("utf-8")
16 #转成utf-8
17
18 print(name)
19 #打印名字
20
21 print(name_gb2312)
22 #打印gb2312编码下的名字
23
24 print(gb2312_to_unicode)
25 #打印unicode编码下的名字
26
27 print(gb2312_to_utf8)
28 #打印utf-8编码下的名字

在python 3.x 中

  终于把这玩意搞完了,希望看到的朋友可以帮忙指出不足与错误的地方。感谢!

时间: 2024-07-30 10:35:52

python - 字符编码篇的相关文章

python字符编码惯用法

本文总结在实际应用中遇到的python字符编码问题,制定一套编码相关的约定,避免编码上的错误. 在写猥琐宝典时需要总结soj上做过的题,准备在总结过程中顺便写一个soj上的题解.题解使用python可读,也就是python可以直接eval的格式,以便于处理.写题解老是copy soj上的题目id,title不是太方便,所以就准备自动生成一个空的题解,里面包含了我做过的题.然而直接从soj上只能拿到自己过了的题的id列表,缺乏其它信息.缺乏的信息可以抽象为soj数据库,其中包含了一个以id为主键的

Python字符编码很难吗?今天一文带你深入!从此不再疑惑!

不论你是有着多年经验的 Python 老司机还是刚入门 Python 不久,你一定遇到过UnicodeEncodeError.UnicodeDecodeError 错误,每当遇到错误我们就拿着 encode.decode 函数翻来覆去的转换,有时试着试着问题就解决了,有时候怎么试都没辙,只有借用 Google 大神帮忙,但似乎很少去关心问题的本质是什么,下次遇到类似的问题重蹈覆辙,那么你有没有想过一次性彻底把 Python 字符编码给搞懂呢? 完全理解字符编码 与 Python 的渊源前,我们有

更改python字符编码以便使用UTF-8的编码url路径

url编码分两种, 一种是unicode, 另一种是gb2312, 今天遇到的一个网站是要将字符编码按照gb2312来编码,用来得到一个先填写blanks后再返回页面的数据,废话少说,需要做的就是先查看你的python的编码是啥,默认是ascii, ? 1 2 3 import sys print sys.getdefaultencoding() # 'ascii' 直接附代码吧: ? 1 import urllib as com ? 1 2 3 4 5 6 7 8 9 10 11 12 13

python 字符编码处理问题总结 彻底击碎乱码!

Python中经常遇到这样的字符编码问题,尤其在处理网页源码时(特别是爬虫中): UnicodeDecodeError: 'XXX' codec can't decode bytes in position 12-15: illegal multibyte... 下面以汉字'哈'来解释作示例解释所有的问题,汉字"哈"的各种编码如下: 1  UNICODE(UTF8-16): 0xC854 2  UTF-8: 0xE59388 3  GBK: 0xB9FE 除此之外还有如gb2312,

Python字符编码详解(转)

1. 字符编码简介 1.1. ASCII ASCII(American Standard Code for Information Interchange),是一种单字节的编码.计算机世界里一开始只有英文,而单字节可以表示256个不同的字符,可以表示所有的英文字符和许多的控制符号.不过ASCII只用到了其中的一半(\x80以下),这也是MBCS得以实现的基础. 1.2. MBCS 然而计算机世界里很快就有了其他语言,单字节的ASCII已无法满足需求.后来每个语言就制定了一套自己的编码,由于单字节

python 字符编码练习

通过下面的练习,加深对python字符编码的认识 # \x00 - \xff 256个字符 >>> a = range(256)>>> b = bytes(a) # 不用参数encoding >>> b b'\x00\x01\x02 ... \xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' >>> b.decode('utf-8') # 报错 Traceback (most recent call l

第七章、Python字符编码

第七章.Python字符编码 一.定义 计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的英文.汉字等字符是二进制数转换之后的结果.通俗的说,按照何种规则将字符存储在计算机中,如'a'用什么表示,称为"编码":反之,将存储在计算机中的二进制数解析显示出来,称为"解码",如同密码学中的加密和解密.在解码过程中,如果使用了错误的解码规则,则导致'a'解析成'b'或者乱码. 字符(Character):是一个信息单位,在计算机里面,一个中文汉字是一个字符,一个英

python成长之路【第五篇】:python字符编码

在2.7环境中我们要写上这一行#-*- coding:utf-8 -*- 为什么我们要加这一行呢?这一样的意思是置顶编码类型为utf-8编码! 首先在看这个问题之前,咱们是否曾想过一个问题? 为什么我们可以在显示器上能看到这些文字.数字.图片.字符.等等信息呢?大家都知道计算机本身只能识别 0 1 的组合,他们是怎么展示这些内容的呢?我们怎么和计算机去沟通呢? 如果我们使用0 1 的组合和计算机沟通你还能看到这些内容吗?还有一个问题就是01的组合对于咱们说几乎看不懂对吧! 那怎么办?如何让计算机

python全栈开发【第六篇】Python字符编码

1.内存和硬盘都是用来存储的. CPU:速度快 硬盘:永久保存 2.文本编辑器存取文件的原理(nodepad++,pycharm,word) 打开编辑器就可以启动一个进程,是在内存中的,所以在编辑器编写的内容也都是存放在内存中的,断电后数据就丢失了.因而需要保存在硬盘上,点击保存按钮或快捷键,就把内存中的数据保存到了硬盘上.在这一点上,我们编写的py文件(没有执行时),跟编写的其他文件没有什么区别,都只是编写一堆字符而已. 3.python解释器执行py文件的原理,例如python  test.