Python 2 中的编码

在 Python 尤其是 Python2 中,编码问题是困扰开发者尤其初学者的一大问题。什么 Unicode/UTF-8/str ,又是 decode/encode 的,搞得人头都大了。其实不然,这有点类似 Java 中 java.io 包一样,看似庞大难懂,但是可以非常精细地定制需求。

编码

计算机只可以存储和处理二进制数据,所以从文字到计算机可以识别的二进制之间需要一道对应关系。于是便有了ASCII(American Standard Code for Information Interchange,美国标准信息交换代码),ASCII使用7位二进制数标记了128(2**7)字符(符号、字母、控制符等),由于1byte=8bit,所以干脆最高位补个0,凑够8位以方便计算和处理。

接着,拉丁语系的技术宅们发现,这128个字符的高位空着的,那么干脆用来表示拉丁语系的主要符号吧,还是使用单字节,但是可以表示的字符数量增加了一倍。这套编码叫做latin-1(iso-8859-1)。

这些宅男们没有想到,区区一个字节256个符号,对于东亚国家来讲,简直呵呵了。拿中文为例,仅常用字符就几千个,于是中国国家标准总局制定了一套中文编码——GB2312。GB2312通过两个字节表示一个汉字,且最高位为0的部分兼容ASCII,最高位为1的部分则通过连续的两个字节表示一个中文字。后来又出现了兼容GB2312的GBK编码。

到这里,依然面临了一个问题:GB2312或者GBK编码中,仅可以表示汉字和英文字符,无法做到多语言文字同时表示。这时候,Unicode(又称万国码)出现了。Unicode采用32位二进制(4字节)表示一个字符,这样便可以一套编码对应多种不同语言。Unicode是一种编码,它的作用是指定字符到二进制数之间的对应关系。但是对于存储和传输,Unicode有几种不同的实现,比较常用的是UTF-8、UTF-16、UTF-32。UTF-32中,每个字符固定占4字节,按照Unicode编码完全映射。而UTF-8和UTF-16则属于变长编码,分别使用最少1个(UTF-8)或2个(UTF-16)字节到最多4个字节来编码。

Python源码的编码

Python2中,如果在源码首行(或在指定sha-bang时的第二行)不显式指定编码,则无法在源码中出现非ASCII字符。这是由于Python解释器默认将源码认作ASCII编码格式。PEP263(点击这里查看)中约定,可以通过如下方式之一来声明源码的编码格式:

# coding=<coding name>

# or

# -*- coding: <encoding name> -*-

# or

# vim: set fileencoding=<encoding name> :

Python中的编码

Python中有两个常用的由basestring派生出来的表示字符串的类型:str,unicode。其中,str类似于C中的字符数组或者Java中的byte数组,事实上你可以将它理解为一个存储二进制内容的容器,str不存储编码信息,如果对str类型的字符串迭代的话,则会按照其在内存中的字节序依次迭代,意味着如果这个字符串存储的是多字节字符(Unicode/GBK等),则会截断这个字符,演示如下:

而对于unicode类型,Python在内存中存储和使用的时候是按照UTF-8格式,在代码中的表示为字符串前加u,如:

而unicode与str之间的转换,则用到了encode和deocde方法。decode表示将一个(str)字符串按照给定的编码解析为unicode类型,encode则表示将一个unicode字符串按照指定编码解析为字节数组(str):

文件读写

内置的open函数打开文件时,read方法读取的是一个str(私以为叫做字节数组更合适),如果读取的是其它编码的文字,则需要decode之后再做使用。

对于使用open函数打开文件之后的写操作(多字节编码的字符串),则需要将需要写入的字符串按照其编码encode为一个str,如果直接写入,则会引发如下错误(如果在代码中加入了encoding声明,则会按照声明的编码格式encode后写入):

除此以外,codecs模块也提供了一个open函数,可以直接指定好编码打开一个文本文件,那么读取到的文件内容则直接是一个unicode字符串。对应的指定编码后的写入文件,则可以直接将unicode写到文件中。通过codecs.open可以避免很多编码问题:

建议

对于Python代码中避免遇到编码问题,有一些小建议:

  • 字符编码声明:在代码开头声明编码格式
  • 使用codecs的open函数处理文本文件
  • 尽可能使用unicode而不是str:在所有字符串的引号前加u
时间: 2024-07-31 14:01:41

Python 2 中的编码的相关文章

python语言中的编码问题

在编程的过程当中,常常会遇到莫名其妙的乱码问题.很多人选择出了问题直接在网上找答案,把别人的例子照搬过来,这是快速解决问题的一个好办法.然而,作为一个严谨求实的开发者,如果不从源头上彻底理解乱码产生的机制,并由此寻求解决问题的根本路径,那么永远不能从码农的阴影中摆脱出来.下面就来一起了解一下计算机编码问题的来龙去脉. ASCII 众所周知,计算机中的所有数据,不论是文字.图片.视频.还是音频文件,本质上最终都是按照类似 01010101 的二进制形式存储的.然而,计算机中的字符,并不能完全以这种

python语言中的编码问题(续)

上文提到了python开发中非常重要的两处设置. 一个是编解码器的默认设置defaultencoding >>> import sys >>> sys.getdefaultencoding()'ascii' 另一个是声明在python文件头部的代码编码方式coding # -*- coding: utf-8 -*- 这两处设置在python的str,unicode对象的encode和decode方法中,有非常重要的作用,直接影响到结果.下面的代码按照目前的设置进行,即d

Python 2中万恶的字符编码

Python2中如果文件存在中文,必须要指定#-*- coding:utf8 -*-或#coding:utf8,否则会报错.那这是为什么呢? 我们知道,在计算机发展初期,计算机只能识别字母,数字和一些基本符号,其使用8位存储空间存储所有的内容,也就是2^8=256个不同的结果,这就是ASCII码.在当时的情况下,并没有想到日后其他语言文字的扩展,随着不断的发展,对计算机的使用越来越广泛,使用8位存储空间早已不能满足人们的日常需求,所以Unicode(万国码)就这样诞生了.顾名思义,Unicode

python中的编码与解码

编码与解码 首先,明确一点,计算机中存储的信息都是二进制的 编码/解码本质上是一种映射(对应关系),比如‘a’用ascii编码则是65,计算机中存储的就是00110101,但是显示的时候不能显示00110101,还是要显示'a',但计算机怎么知道00110101是'a'呢,这就需要解码,当选择用ascii解码时,当计算机读到00110101时就到对应的ascii表里一查发现是'a',就显示为'a' 编码:真实字符与二进制串的对应关系,真实字符→二进制串 解码:二进制串与真实字符的对应关系,二进制

python中的编码声明

python中的第一行,目的就是指出,你想要你的这个文件中的代码用什么可执行程序去运行它,就这么简单 #!/usr/bin/python 相当于写死了 python 路径(是告诉OS执行这个py时,调用 /usr/bin 下的 python 解释器:) #!/usr/bin/env python 会去环境设置寻找python目录,推荐这种写法(目的是为了OS防止user没有将python 装在默认的 /usr/bin 路径里.在Linux类的OS环境下有意义) 如果要在python2的py文件里

浅谈Python中的编码规则

注:本人用Python3.4作为学习版本,以下学习心得只适用于Python3.4. 之前拜读了金角大王Alex关于编码的解答,收获颇多.特此致谢,以下仅谈一谈作为一个初学者,对编码的理解. 我所了解的编码,大致分为两类:第一类是支持中文的编码集:第二类是支持英文的编码集.至于别国的编码集,暂且不做讨论. 常见编码:ASCII:Unicode:UTF-8:big5,:GB2312:GBK:GB18030 接下来,我对以上编码进行分类: 只支持英文和特殊字符的编码:ASCII ASCII是基于拉丁字

python中的编码问题:以ascii和unicode为主线

  1.unicode.gbk.gb2312.utf-8的关系 http://www.pythonclub.org/python-basic/encode-detail 这篇文章写的比较好,utf-8是unicode的一种实现方式,unicode.gbk.gb2312是编码字符集: 2.python中的中文编码问题 2.1 .py文件中的编码 Python 默认脚本文件都是 ANSCII 编码的,当文件 中有非 ANSCII 编码范围内的字符的时候就要使用"编码指示"来修正. 一个mo

HTTP1.1中CHUNKED编码解析(转载)

HTTP1.1中CHUNKED编码解析 一般HTTP通信时,会使用Content-Length头信息性来通知用户代理(通常意义上是浏览器)服务器发送的文档内容长度,该头信息定义于HTTP1.0协议RFC  1945  10.4章节中.浏览器接收到此头信息后,接受完Content-Length中定义的长度字节后开始解析页面,但如果服务端有部分数据延迟发送吗,则会出现浏览器白屏,造成比较糟糕的用户体验. 解决方案是在HTTP1.1协议中,RFC  2616中14.41章节中定义的Transfer-E

python国际使用的编码规范

目前常用的编码规范为 PEP8 该规范的内容规定: 一 代码编排1 缩进.4个空格的缩进(编辑器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格.2 每行最大长度79,换行可以使用反斜杠,最好使用圆括号.换行点要在操作符的后边敲回车.3 类和top-level函数定义之间空两行:类中的方法定义之间空一行:函数内逻辑无关段落之间空一行:其他地方尽量不要再空行. 二 文档编排1 模块内容的顺序:模块说明和docstring-import-globals&constants-其他定义.其中