本文主要是针对python2,为了支持中文,必须指定文件编码或者字符串默认编码的问题进行更一步阐述
python3由于字符串采用unicode编码,文件默认编码为UTF-8,不再需要添加声明或者指定字符串编码
作用是声明编码格式,定义源代码的编码. 如果没有定义, 此源码中是不可以包含中文字符串的.
PEP 0263中对此有详细说明(下文有相关内容的翻译)
PEP 0263 -- Defining Python Source Code Encodings
https://www.python.org/dev/peps/pep-0263/
是设置默认的string的编码格式;
import sys
reload(sys)
sys.setdefaultencoding('utf8')
而python2.x的的defaultencoding是ascii,这也就是大多数python编码报错的原因
“UnicodeDecodeError: 'ascii' codec can't decode byte ......”
我们知道在Python源码的头文件中要声明编码方式,之所以要声明未编码类型 ,主要是中文出错的问题。如果你不只是会用到ascii码,很多人都写得都有点差别:
# coding=utf-8
# coding:utf-8
# -*- coding:utf-8 -*-
那么怎样写才是有效地呢,哪些是无效的呢?
这可以查看下http://www.python.org/dev/peps/pep-0263/的解释
概要:
这个PEP的目的是介绍在一个Python源文件中如何声明编码的语法。随后Python解释器会在解释文件的时候用到这些编码信息。最显著的是源文件中对Unicode的解释,使得在一个能识别Unicode的编辑器中使用如FUT-8编码成为可能
怎么声明呢?
如果在Python中我们并没有声明别的编码方式,就是以ASCII编码作为标准编码方式的
为了定义源文件的编码方式,一个魔法是的声明应当被放在这个文件的第一行或者是第二行例如:#coding=
或者(使用流行编辑器中的格式化方式)
#!/usr/bin/python # -*- coding:
-*- 或者
#!/usr/bin/python # vim: set fileencoding=
: 不管怎么样,这些在第一行或者第二行的声明都要符合正则表达式
"coding[:=]\s*([-\w.]+)"
示例
下面是一些示例,在Python源文件顶部,声明的源代码编码所采用的不同样式
1. 指定执行脚本的解释器,并使用Emacs风格的文件编码注释:
#!/usr/bin/python # -*- coding: latin-1 -*- import os, sys ...
#!/usr/bin/python # -*- coding: iso-8859-15 -*- import os, sys ...
#!/usr/bin/python # -*- coding: ascii -*- import os, sys ...
2. 不指定解释器,使用注释语句:
# This Python file uses the following encoding: utf-8 import os, sys ...
3. 各种文本编辑器可能有不同的方法来定义文件的编码,例如。
#!/usr/local/bin/python # coding: latin-1 import os, sys ...
4. 如果不编码注释,Python的解析器将默认为ASCII文本:
#!/usr/local/bin/python import os, sys ...
5. 以下是一些无效的编码声明:
没有 "coding:" 前缀:
#!/usr/local/bin/python # latin-1 import os, sys ...
编码声明没有在第一行和第二行:
#!/usr/local/bin/python # # -*- coding: latin-1 -*- import os, sys ...
不支持的编码类型:
#!/usr/local/bin/python # -*- coding: utf-42 -*- import os, sys ...
以上几个例子充分说明了哪些是正确的写法,哪些是正确的写法
所以我们就可以知道为什么使用冒号coding:或者等号coding=都可以了,如果声明的编码python不能识别就会报错
python 支持3种编码声明中,一般常用能见到前两种
# -*- coding: utf-8 -*- 这种写法是为了兼容Emacs的编码声明
# coding=utf-8 短一点,但Emacs不能用
这里要注意的是:
Python 里面的编码和解码也就是 unicode 和 str 这两种形式的相互转化。
编码是 unicode -> str,相反的,解码就是 str -> unicode。
关于文件开头的"编码指示",也就是 # -*- coding: -*- 这个语句。Python 默认脚本文件都是 UTF-8 编码的,当文件中有非 UTF-8 编码范围内的字符的时候就要使用"编码指示"来修正.
至于sys.defaultencoding,这个在解码时没有明确指明解码方式的时候使用。比如如下代码:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
s = '中文' # 注意这里的 str 是 str 类型的,而不是 unicode
s.encode('gb18030')
这句代码将 s 重新编码为 gb18030 的格式,即进行 unicode -> str 的转换。因为 s 本身就是 str 类型(python2字符串默认不是unicode)的,因此 Python 会自动的先将 s 解码为 unicode ,然后再编码成 gb18030。因为解码是python自动进行的,我们没有指明解码方式,python 就会使用 sys.defaultencoding 指明的方式来解码。很多情况下 sys.defaultencoding 是
ANSCII,如果 s 不是这个类型就会出错。拿上面的情况来说,我的sys.defaultencoding是anscii,而 s 的编码方式和文件的编码方式一致,是 utf8 的,所以出错了:
“UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128) "
对于这种情况,我们可以在字符串前加u将s直接指定为unicode字符串,
#! /usr/bin/env python
# -*- coding: utf-8 -*-
s = u'中文' # 注意这里的s是unicode字符,不需要再解码
s.encode("GB18030")
一般情况下,从文件或者网络中获取字符串是无法直接指定为unicode的,
这种时候,可以通过以下两种方法来解决:
一、明确的指示出 s 的编码方式
#! /usr/bin/env python
# -*- coding: utf-8 -*-
s = '中文'
s.decode('utf-8').encode('gb18030')
二、更改 sys.defaultencoding 为文件的编码方式
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys
reload(sys) # Python2.5 初始化后会删除 sys.setdefaultencoding 这个方法,我们需要重新载入
sys.setdefaultencoding('utf-8')
str = '中文'
str.encode('gb18030')
以上内容根据以下博主的文章整理
---------------------
作者:suibianshen2012
来源:CSDN
原文:python中coding:utf-8和setdefaultencoding区别作者:wlwxww
来源:CSDN
原文:为什么有时候必须添加sys.setdefaultencoding('utf-8')作者:不笑猫
来源:CSDN
原文:python文件编码说明 coding=utf-8