• 欢迎访问DBA的辛酸事儿,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站
  • 欢迎大家关注博主公众号:DBA的辛酸事儿
  • 博文中若有错误的地方,请大家指正,大家的指正是我前进的动力

Python报错:UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe9 in position 0: ordinal not in range(128)

python SEian.G 4年前 (2021-03-16) 3183次浏览 已收录 0个评论

最近在用Python开发的时候,遇到些对中文数据的处理,报出了如下错误:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)

之前也遇到过,但是没有深入的去了解和测试,今天借此问题,对python的编码问题做个详细的学习;首先说明一点的是,目前公司的开发环境是Python 2.7;

从报错信息看,应该是编码的问题导致的,默认情况下,Python采用的是ascii编码方式,如下所示:

python -c "import sys; print sys.getdefaultencoding()"
ascii

查询网上博客,也发现很多人在说是编码的问题:“Python在进行编码方式之间的转换时,会将 unicode 作为“中间编码”,但 unicode 最大只有 128 那么长,所以这里当尝试将 ascii 编码字符串转换成”中间编码” unicode 时由于超出了其范围,就报出了如上错误。”

同时网上的很多解决方法是在python文件的前面加上如下代码:

import sys
defaultencoding = 'utf-8'
if sys.getdefaultencoding() != defaultencoding:
reload(sys)
sys.setdefaultencoding(defaultencoding)

然后,根据网上给出的解决方法,在代码最开始添加上述代码,发现问题解决了;但是,经测试发现,这种方法仅适用于python2.7,在python3中不适用,因为python3已经取消了reload,而在对于编码方法做了很大的调整

Python3 最重要的一项改进之一就是解决了 Python2 中字符串与字符编码遗留下来的这个大坑。

Python2 字符串设计上的一些缺陷:

使用 ASCII 码作为默认编码方式,对中文处理很不友好。

把字符串的牵强地分为 unicode 和 str 两种类型,误导开发者

当然这并不算 Bug,只要处理的时候多留心也可以避免这些坑。但在 Python3 两个问题都很好的解决了。

首先,Python3 把系统默认编码设置为 UTF-8,如下所示:

>>> import sys
>>> sys.getdefaultencoding()
'utf-8'

下面我们来做一个简单的测试:

# -*- coding: utf-8 -*-   
s = '中文'  # 注意这里的 str 是 str 类型的,而不是 unicode   
s.encode('gb18030')  

执行结果

python t1.py 
Traceback (most recent call last):
  File "t1.py", line 3, in 
    s.encode('gb18030')   
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

上述代码将 s 重新编码为 gb18030的格式,即进行unicode -> string的转换。因为 s 本身就是 string类型的,因此 Python 会自动的先将 s 解码为 unicode ,然后再编码成 gb18030。因为解码是python自动进行的,我们没有指明解码方式,python 就会使用 sys.defaultencoding指明的方式来解码。python2.7环境下 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) __

Python 里面的编码和解码也就是 unicode 和 string 这两种形式的相互转化.

编码是 unicode -> str,相反的,解码就 是 str -> unicode

剩下的问题就是确定何时需要进行编码或者解码了.

关于文件开头的”编码指示”,也就是 # -*- coding: -*- 这个语句。Python 默认脚本文件都是 UTF-8 编码的,当文件中有非 UTF-8 编码范围内的字符的时候就要使用”编码指示”来修正. 关于 sys.defaultencoding,这个在解码没有明确指明解码方式的时候使用。比如上述简单的小测试

错误之前在解决,首先要了解unicode和utf-8的区别。

python中字符串类型分为byte string 和unicode string两种。

如果在python文件中指定编码方式为utf-8(#coding=utf-8),那么所有带中文的字符串都会被认为是utf-8编码的byte string(例如:mystr=”你好,李焕英”),但是在函数中所产生的字符串则被认为是unicode string

问题就出在这边,unicode string 和byte string是不可以混合使用的,一旦混合使用了,就会产生这样的错误。例如:

self.response.out.write(“你好,李焕英”+self.request.get(“args”))

其中,”你好,李焕英”被认为是byte string,而self.request.get(“args”)的返回值被认为是unicode string。由于预设的解码器是ascii,所以就不能识别中文byte string。然后就报错了。

以下有两个解决方法:

第一种:明确的指示出 s 的编码方式

# -*- coding: utf-8 -*- 
s = '中文' 
s.decode('utf-8').encode('gb18030')

第二种:更改sys.defaultencoding为文件的编码方式

# -*- coding: utf-8 -*- 
import sys     #要重新载入sys。因为 Python 初始化后会删除 sys.setdefaultencoding 这个方法
reload(sys) 
sys.setdefaultencoding('utf-8') 

结合上述测试的小案例,那么针对这种情况下,最后给出两种终极解决办法

1)第一种:这里我们将Python的默认编码方式修改为utf-8,就可以规避上述问题的发生,具体方式,我们在Python文件的前面加上如下代码:

import sys
defaultencoding = 'utf-8'
if sys.getdefaultencoding() != defaultencoding:
    reload(sys)
    sys.setdefaultencoding(defaultencoding)

2)第二种:我们在Python安装目录下的site-packages目录下添加一个sitecustomize.py文件,内容如下:

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

这种方式可以解决所有项目的encoding问题,具体说明可参考Python安装目录下的site.py文件;

参考链接:

https://blog.csdn.net/l1028386804/article/details/78976807

Python报错:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)


如果您觉得本站对你有帮助,那么可以收藏和推荐本站,帮助本站更好地发展,在此谢过各位网友的支持。
转载请注明原文链接:Python报错:UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe9 in position 0: ordinal not in range(128)
喜欢 (2)
SEian.G
关于作者:
用心去记录工作,用心去感受生活,用心去学着成长;座右铭:苦练七十二变,笑对八十一难
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址