也来谈谈python编码

1、coding:utf-8

让咱们先来看一个示例,源码文件是utf-8格式:html

print('你好 python')

当使用python2执行该程序时会收到一下报错:python

File "./hello_world.py", line 2
SyntaxError: Non-ASCII character '\xe4' in file ./hello_world.py on line 2, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

错误提示的意思就是存在非ASCII字符,可是却没有encoding declared,同时给了一个链接并说明包含详细缘由,这个连接是一个PEP(python enhancement proper)。
enter image description here编码

这个PEP的内容总结下来就是:
这行代码用于声明代码文件的编码格式,这个信息能够帮助python解析器使用指定的正确编码来解释代码文件。这样就能够容许直接在代码中使用utf-8编码了。
另外须要注意的是:声明的编码格式要和代码文件的格式同样才行,不然会报错。code

来看另一个例子:htm

# -*- coding:utf-8 -*-
print('你好 python')

将这段代码保存为ANSI格式,并执行,会获得如下报错:ip

$ python ./hello_python.py
  File "./hello_python.py", line 2
SyntaxError: (unicode error) 'utf-8' codec can't decode byte 0xc4 in position 0: invalid continuation byte

因此说指定编码的时候也不能所有统一指定为utf-8,而是要根据源码文件的格式来指定,二者要一致才行。utf-8

另外又在python的官方文档找到一个说明:
enter image description here
意思就是说:默认状况下,python解释器(python2)把源代码文件当作ASCII编码来处理,若是源码文件是其余格式就须要经过一个特殊的注释来讲明,也就是:coding:utf-8,固然编码格式支持多中,具体看codecs的支持状况。
这里其实也是因为python诞生的太早了,那时候Unicode都尚未诞生,所以当时做者也只能选择ASCII做为默认的编码格式。python3已经将默认编码格式改成UTF-8ci

总结

因此总结下来就是,python2中,该行代码的做用是当源代码文件不是ASCII编码时,经过该行代码告诉python解释器正确的编码格式,这样python解释器才能正常解释其中的字符。
另外,因为python3已经修改成默认状况下,将源代码文件当作UTF-8格式来处理,同时咱们写代码时如今一般都会使用UTF-8格式来存储,所以python3实际上是不用再写这一行代码的,除非你的源代码文件不是UTF-8格式的。unicode

2、sys.setdefaultencoding('utf-8')

先来看一个例子:文档

# -*- coding:utf-8 -*-
s = '你好'
s.encode('gb2312')

执行以上代码会收到下面的报错:

Traceback (most recent call last):
  File "./hello_str.py", line 3, in <module>
    s.encode('gb2312')
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

第一次遇到这个报错时,感受很奇怪,明明我作的是encode操做,可是为何报错确实decode失败呢?
这里就是先提一下了:Python里面的编码和解码也就是unicode和str这两种形式的相互转化。编码是unicode->str,相反的,解码就是str->unicode。
而上面定义的s是str类型的,所以当调用encode时,其实默认是先作了decode,转换为Unicode,而后再执行encode编码为指定的编码的,这里报错的缘由就是当作隐式编码、解码时使用的默认格式是:ASCII,可是因为s是utf-8的编码,因此解码就失败了。
解决办法:
一、在文件头部添加sys.setdefaultencoding('utf-8')修改默认的编码、解码格式。

import sys
sys.setdefaultencoding('utf-8')

二、避免由程序作隐式的编码、解码,也就是说要明确str-Unicode的转换规则,可是须要编码时要确认类型是Unicode,若是不是就手动指定正确的解码格式转换为Unicode。

s.decode('utf-8').encode('gb2312')

总结

setdefaultencoding主要在编码、解码没有明确指明编码、解码格式的时候使用。

3、参考资料

一、PEP 263
二、source-code-encoding

相关文章
相关标签/搜索