千锋教育-做有情怀、有良心、有品质的职业教育机构

400-811-9990
手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

上海
  • 北京
  • 郑州
  • 武汉
  • 成都
  • 西安
  • 沈阳
  • 广州
  • 南京
  • 深圳
  • 大连
  • 青岛
  • 杭州
  • 重庆
当前位置:广州千锋IT培训  >  技术干货  >  解决Python编码问题

解决Python编码问题

来源:千锋教育
发布人:xqq
时间: 2023-11-07 20:27:19

1.基本概念

字符集(Characterset)

解释:文字和符合的总称

常见字符集:

Unicode字符集

ASCII字符集(Unicode子集)

GB2312字符集

编码方法(Encoding)

解释:将字符对应到字节的方法,部分字符集和编码方法名称一样。

常见编码方法:

UTF-8:可对Unicode字符进行编码

GB2312

ASCII

编码(Encode)

解释:将字符集中字符按照一定规则转换成字节

解码(Decode)

解释:与编码相反,将字节转换为字符集中的字符

字符集与编码方法的关系

每个字符集都有对应的编码方法

一种字符集可能有多种编码方法

不同的编码方法得到的字节不同,占用存储空间也不一样

例如Unicode字符可以使用UTF-8/ASCII/GBK等方法编码

Unicode字符集包含世界上大部分字符,很多其他字符集有的字符它都有,是他们的超集

大部分字符集可以理解为Unicode的子集

实际上,除了Unicode之外所谓的字符集主要是对Unicode部分字符编码而已(定义编码方式)

一种编码不必支持Unicode的所有字符(通常把它能支持的那部分称为它的字符集)

2.关于编码的错误和解决方法

在开发过程中,我们所接触的字符集大多都是Unicode,大部分报错都是关于编码和解码的。

2.1.编码错误UnicodeEncodeError

2.1.1.错误分析

导致该错误的原因通常是编码方法支持的Unicode字符不全;在工作中,你写了一个txt中文文档,想用ascii编码去保存这个文件,就会报这种错误。

错误复现:

我们知道ascii不支持字符中,那我们用ascii编码方法对Unicode码中进行编码:

#-*-encoding:utf-8-*-

u"中".encode(encoding='ascii')

报错如下:

UnicodeEncodeError:'ascii'codeccan'tencodecharacter'\u4e2d'inposition0:ordinalnotinrange(128)

这是一个UnicodeEncodeError类型的错误,提示无法使用指定的编码方法对字符进行编码,报错提示中可以得到3个信息:

当前使用的是acsii编码方法

被编码的字符是'\u4e2d'

ascii编码方法能支持的字符有128个

有时候我们还可以利用这个提示查看编码方法支持的字符个数:

#-*-encoding:utf-8-*-

u"中".encode(encoding='iso-8859-1')

报错:

UnicodeEncodeError:'latin-1'codeccan'tencodecharacter'\u4e2d'inposition0:ordinalnotinrange(256)

通过报错提示可以看出iso-8859-1能编256个字符。

接着,我们来看下用支持中文的utf-8编码方法进行编码能得到什么结果:

#-*-encoding:utf-8-*-

s=u"中".encode(encoding='utf-8')

print("s:",s)

print("s==中?",s=='中')

print("typeofs:",type(s))

print("str==bytes?",bytes==type(s))

输出:

('s:','\xe4\xb8\xad')

('s==\xe4\xb8\xad?',True)

('typeofs:',)

('str==bytes?',True)

从输出的结果可以得到:

-编码得到的对象跟我们直接定义的字符串是一样的,都是str

-str就是bytes(python中)

2.1.2.解决方法

UnicodeEncodeError是说编码方法支持的字符不全,而UTF-8编码就能很好地对Unicode编码,所以只要把编码方法指定为utf-8就可以了。

在python2中:

如果你调用encode方法但没有指定encoding参数,那很可能使用了系统默认的参数,就像:

#-*-encoding:utf-8-*-

importsys

print"defaultencodingis%s."%sys.getdefaultencoding()

u'中'.encode()

输出:

defaultencodingisascii.

UnicodeEncodeError:'ascii'codeccan'tencodecharacteru'\u4e2d'inposition0:ordinalnotinrange(128)

可以手动指定encoding参数,也可以修改python默认编码方法:

#-*-encoding:utf-8-*-

importsys

reload(sys)

sys.setdefaultencoding('utf-8')#必须在reload之后调用

printu'中'.encode()

在python3中:

在python3中你很难看到UnicodeEncodeError了,因为python3的默认编码就是utf-8,而Unicode字符都可以用utf-8编码方法编码。

2.2.编码错误UnicodeDecodeError

2.2.1.错误分析

导致该错误的原因是使用了错误的解码方式把字节数据还原成字符。例如在工作中,有一个utf-8生成中文文档,我们选择用ascii编码解码,就会报这个错。

错误复现:

我们知道python中字符串和字节是一样,我们可以定义一个中文字符串,通过ascii来解码生成Unicode,复现这个错误:

#-*-encoding:utf-8-*-

print'中'.decode(encoding='ascii')

输出:

UnicodeDecodeError:'ascii'codeccan'tdecodebyte0xe4inposition0:ordinalnotinrange(128)

注意,这是一个UnicodeDecodeError错误,区别于编码错误UnicodeEncodeError,它提示无法把字节0xe4(实际上中对应三字节,0xe4是第一个)解码成Unicode。0xe4转换为10进制是228,已经超过127了,所以ascii无能力了。

2.2.2.解决方法

我们需要知道生成字节的编码方式才能进行还原,就好像对一个文件进行了加密,必须得知道加密的密码才能把文件还原,而解码方式(或者称为编码)就是那个密码。所以不管是python2还是python3直接去修改默认编码为UTF-8不一定能解决问题,具体的方法有两种:

通过源码找到解码失败的字节是使用那种编码生成的

对报错的字节数据使用各种常见的编码进行解码,观察哪一种是正确的

以一个例子来说明为什么直接设置默认编码为UTF-8不能有效解决UnicodeDecodeError问题

python文件头指定了编码为,在声明字符串时候将会使用指定的编码转换为字节:

#-*-encoding:GBK-*-

s="张"

print("sis",s)

s_unicode=u'张'

print("encodingwithGBKis",s_unicode.encode("GBK"))

print("encodingwithUTF-8is",s_unicode.encode("UTF-8"))

输出:

('sis','\xd5\xc5')

('encodingwithGBKis','\xd5\xc5')

('encodingwithUTF-8is','\xe5\xbc\xa0')

在文件头中指定了GBK编码后默认情况下字符张就会被编码为\xd5\xc5,这与我们手动用GBK编码得到结果一致,而使用utf-8编码得到的是3个字节的数据\xe5\xbc\xa0(使用了更多的存储空间)。

例子开始了,在python2中将一个dict转换成json:

#-*-encoding:GBK-*-

importjson

d={'name':"张",'sex':u'man'}

print(json.dumps(d))

输出:

UnicodeDecodeError:'utf8'codeccan'tdecodebyte0xd5inposition0:invalidcontinuationbyte

错误说无法使用utf-8解码0xd5,0xd5也就是GBK中的张,我们知道这个字节是用GBK生成的,这个时候可以设置json.dumps的encoding参数解决:

#-*-encoding:GBK-*-

importjson

d={'name':"张",'sex':u'man'}

print(json.dumps(d,encoding='gbk'))

修改一下代码,继续使用我们熟悉的utf-8编码来执行:

#-*-encoding:utf-8-*-

importjson

d={'name':"张",'sex':u'man'}

print(json.dumps(d,encoding='utf-8'))

输出:

{"name":"\u5f20","sex":"man"}

发现name是unicode,使用ensure_ascii=False,不强制转换成ascii:

#-*-encoding:utf-8-*-

importjson

d={'name':"张",'sex':u'man'}

print(json.dumps(d,encoding='utf-8',ensure_ascii=False))

输出:

File"/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py",line251,indumps

sort_keys=sort_keys,**kw).encode(obj)

File"/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py",line210,inencode

return''.join(chunks)

UnicodeDecodeError:'ascii'codeccan'tdecodebyte0xe5inposition1:ordinalnotinrange(128)

纳尼,文件头也是utf-8,也指定了utf-8怎么还是报错?错误提示用ascii去解码0xe5字节,在上面的代码输出中可以知道0xe5是utf-8对字符张编码的第一个字节,报错的原因是用ascii去解析utf-8生成的字节了。我们并没有设置哪个地方使用ascii解码,应该是系统默认的编码,尝试设置系统默认编码再执行:

#-*-encoding:utf-8-*-

importsys

reload(sys)

sys.setdefaultencoding('utf-8')

importjson

d={'name':"张",'sex':u'man'}

print(json.dumps(d,encoding='utf-8',ensure_ascii=False))

输出:

{"name":"张","sex":"man"}

3.总结

3.1.python2和python3对字符串的处理区别

Python2

默认编码是ascii

Python3

importsys;sys.setdefaultencoding('utf-8')

3.2.为什么不全用UTF-8编码?

UTF-8包含的字符更多,占用的内存和磁盘空间也更大,比如对汉字张,utf-8是3个字节,gbk是2个字节。

3.3.如何快速解决UnicodeEncodeError错误?

python3中基本不会出现,python2中尝试设置默认编码为utf-8。

3.4.快速解决UnicodeDecodeError?

需要知道出错的字节是使用哪种编码方式生成的,然后尝试把默认编码设置成这种。

以上内容为大家介绍了解决Python编码问题,希望对大家有所帮助,如果想要了解更多Python相关知识,请关注IT培训机构:千锋教育。http://www.mobiletrain.org/

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

猜你喜欢LIKE

python 列表元素的增加

2023-11-07

Python 决策树算法思想

2023-11-07

Python 枚举

2023-11-07

最新文章NEW

python 抽象类和抽象接口

2023-11-07

Python 分类技术

2023-11-07

Python C代码统计工具代码的效果验证

2023-11-07

相关推荐HOT

更多>>

快速通道 更多>>

最新开班信息 更多>>

网友热搜 更多>>