我们看到的输入输出都是'字符'(characters),计算机(程序)并不能直接处理,需要转化成字节数据(bytes),因为程序只能处理 bytes 数据。
例如:文件、网络传输等,处理的都是 bytes 数据——二进制数字。
孤立的 byte 是毫无意义的,所以我们来赋予他们含义。就引入'字符集'的概念,'字符集'就是一个对应的一个字符的表。
该表用于赋予 byte 意义。还需要知道一个点:因为 ASCII 字符集支持的字符太少,不能表示各个国家语言中的字符。所以就发明了
Unicode ——万国码,该字符集包含了你能用到的所有的字符。
在 python 中字符串分为两个对象:
和
- str
- unicode
- unicode_obj.encode() ——> bytes '编码'(encode)
- bytes_obj.decode() ——> unicode '解码'(decode)
UTF-8 是最流行的一种对 Unicode 进行传播和存储的编码方式。所以,多用它作为编码方式。
- s = 'hello' # str
- u = u'你好' # unicode
- back_to_bytes = u.encode('utf-8')
- back_to_utf8 = back_to_bytes.decode('utf-8') # 或 unicode(s, 'utf-8')
正如前面所说的,计算机只能操作 bytes,所以 Python 在编译原文件的时候,会先把源文件进行编码,默认以'ASCII'进行编码。这就是为什么如果源文件中带有'中文',需要在源文件的起始行声明编码方式。
完成编码后,源码中的所有字符,都变成了 bytes 计算机就可以进行编译和处理了。编译过程:
根据这个过程,在自己的代码中也应该按照这个逻辑处理,意思是:
参考:
- Content-Type:text/html; charset=UTF-8
在 python 中处理编码问题,会出现很多问题,这里就不一一列举。
这些问题大都是使用了不匹配的编码方式进行解码、编码造成的。而 python 为了语法更加简介,在一些内置方法中,使用了一些隐性转换。这种隐形的转换带了的便捷的同时也会带来一些非预期的错误。下面就一一道来。
- a = "abc" + u"bcd"
,Python 会如此转换 "abc".decode(sys.getdefaultencoding()) 然后将两个 Unicode 字符合并。
- a = "abc" + u"bcd"
和
- str()
,
- unicode()
默认为:ASCII,这就是为什么
- sys.getdefaultencoding()
和
- str(u'中文')
分别会报错:UnicodeEncodeError 和 UnicodeDecodeError。因为 ASCII 编码方式,编码/解码不了中文(支持的字符有限)。
- unicode('中文')
函数
函数,会对输出的内容进行编码,这是因为:所谓的输出,也是从一个程序到另外一个程序。程序之间的交互都是都是传递 bytes。比方说
,就是把数据传递给 终端 ,终端也是个程序,所以
函数就把需要输出的内容编码成了 bytes,采用那种编码方式,就是
参数决定的。
- sys.stdout.encoding
在交互环境下(python、ipython)输入的数据的编码则由
参数决定。参考:
- sys.stdin.encoding
python 的默认编发方式为 ASCII。
如何改变 python 的默认编码方式?:
- import sys
- # sys.setdefaultencoding() does not exist, here!
- reload(sys) # Reload does the trick!
- sys.setdefaultencoding('UTF8')
为什么要重载
模块?
- sys
因为如果在编译
文件的之前,改变默认编码,会影响 Python 的编译。 当编译完,再重载
- .py
模块,它就是变成了第三方模块,可以随便更改,不回影响编译。
- sys
函数才可以调用。参考:
- setdefaultencoding()
本片文章没有列举出常见的异常,因为如果看懂了上面所有的解释。再按照下面的姿势使用,那么 python2 中的编码问题,因该就不会再困扰你了。
来源: