一,编码
字符串是Python中最常用的数据类型,而且很多时候你会用到一些不属于标准ASCII字符集的字符,这时候代码就很可能抛出UnicodeDecodeError: ascii codec cant decode byte 0xc4 in position 10: ordinal not in range(128)异常。这种异常在Python中很容易遇到,尤其是在Python2.x中。
字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。
原有编码 --》 unicode编码 --》 目的编码
decode("utf-8") --> unicode --> encode("gbk")
但是,Python 2.x的默认编码格式是ASCII,就是说,在没有指定Python源码编码格式的情况下,源码中的所有字符都会被默认为ASCII码。也因为这个根本原因,在Python 2.x中经常会遇UnicodeDecodeError或者UnicodeEncodeError的异常。
二,Python 3.x中的Unicode
在Python 3.0之后的版本中,所有的字符串都是使用Unicode编码的字符串序列,同时还有以下几个改进:
1、默认编码格式改为unicode
2、所有的Python内置模块都支持unicode
3、不再支持u中文的语法格式
所以,对于Python 3.x来说,编码问题已经不再是个大的问题,基本上很少遇到编码异常。
三,Python 2.x常见问题Python中常见的几种编码异常有SyntaxError: Non-ASCII character、UnicodeDecodeError和UnicodeEncodeError等。
1、SyntaxError: Non-ASCII character
这种异常最不容易出现,也最容易处理,主要原因是Python源码文件中有非ASCII字符,而且同时没有声明源码编码格式,例如:
s = “中文”
print(s)
# 抛出异常
解决: 文件头部声明编码# -*- coding: utf-8 -*-
Python2中,如果在源码首行(或在指定sha-bang时的第二行)不显式指定编码,则无法在源码中出现非ASCII字符。这是由于Python解释器默认将源码认作ASCII编码格式。
2、UnicodeDecodeError
这个异常有时候会在调用decode方法时出现,原因是Python打算将其他编码的字符转化为Unicode编码,但是字符本身的编码格式和decode方法传入的编码格式不一致,例如:
# -*- coding: utf-8 -*-
s = “中文”
s.decode(“gb2312”)
# UnicodeDecodeError: gb2312 codec cant decode bytes in position 2-3: illegal multibyte sequenceprint s
Note:上面这段代码中字符串s的编码格式是utf-8(# -*- coding: utf-8 -*-声明的意思是:当前.py文件中所有的字符串是utf-8编码的),但是在使用decode方法转化为Unicode编码时传入的参数是‘gb2312’,因此在转化的时候抛出UnicodeDecodeError异常。
还有一种情况是在encode的时候:
# -*- coding: utf-8 -*-
s = 中文
s.encode(“gb2312”)
# UnicodeDecodeError: ascii codec cant decode byte 0xe4 in position 0: ordinal not in range(128)print s
Note:这里的s是utf-8编码的,直接使用s.encode(gb2312)实际使用了系统默认defalutencoding(ascii)来解码,等价于s.decode(defaultencoding).encode(gb2312),而s的实际编码与defaultencoding不同。
3、UnicodeEncodeError
错误的使用decode和encode方法会出现这种异常,比如:使用decode方法将Unicode字符串转化的时候:
# -*- coding: utf-8 -*-
s = u“中文”
s.decode(“utf-8”)
# UnicodeEncodeError: ascii codec cant encode characters in position 0-1: ordinal not in range(128)print s
四,Python编写中的建议
1、声明编码格式
对Python编码问题的最基本的解决方法:在Python源码文件中声明编码格式,最常见的声明方式如下:
# -*- coding: <encoding name> -*-
Note:其中<encoding name>是代码所需要的编码格式,它可以是任意一种Python支持的格式,一般都会使用utf-8的编码格式。# -*- coding: utf-8 -*-是Python文件声明,意思是:当前.py文件中所有的字符串是utf-8编码的,不是读取的文件是用utf-8编码读取的!
2、使用u中文替代中文(py2)
str1 = 中文编码
str2 = u中文编码
Python中有以上两种声明字符串变量的方式,它们的主要区别是编码格式的不同,其中,str1的编码格式和Python文件声明的编码格式一致,而str2的编码格式则是Unicode。如果你要声明的字符串变量中存在非ASCII的字符,那么最好使用str2的声明格式,这样你就可以不需要执行decode,直接对字符串进行操作,可以避免一些出现异常的情况。
Note:python3不支持u的声明方式。
主要是因为Python 2.x的编码设计问题。升级到Python 3.x可以解决大部分因为编码产生的异常问题。