UnicodeDecodeError,无效的连续字节

474
为什么以下项目失败?为什么使用 "latin-1" 编解码器会成功?
o = "a test of \xe9 char" #I want this to remain a string as this is what I am receiving
v = o.decode("utf-8")

这导致:
 Traceback (most recent call last):  
 File "<stdin>", line 1, in <module>  
 File "C:\Python27\lib\encodings\utf_8.py",
 line 16, in decode
     return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError:
 'utf8' codec can't decode byte 0xe9 in position 10: invalid continuation byte
13个回答

540

当我尝试使用 pandas.read_csv 方法打开CSV文件时,我遇到了同样的错误。

解决方法是将编码更改为latin-1

pd.read_csv('ml-100k/u.item', sep='|', names=m_cols , encoding='latin-1')

12
这个方法真正解决了问题吗?它不是只是告诉 pandas 忽略这个字节,通过降低编码的复杂度来实现的吗? - Yu Chen
1
适用于内置的 open 函数。谢谢。 - Leonardo Maffei

360

在二进制中,0xE9看起来像是1110 1001。如果你阅读维基百科上的UTF-8相关文章,你会发现这样的一个字节后面必须跟着两个形如10xx xxxx的字节。例如:

>>> b'\xe9\x80\x80'.decode('utf-8')
u'\u9000'

但这只是异常的机械原因。在这种情况下,你有一个几乎肯定是用Latin 1编码的字符串。你可以看到UTF-8和Latin 1的区别:

>>> u'\xe9'.encode('utf-8')
b'\xc3\xa9'
>>> u'\xe9'.encode('latin-1')
b'\xe9'

(注意,这里混用了Python 2和3的表示方式。输入在任何版本的Python中都是有效的,但你的Python解释器不太可能以这种方式同时显示Unicode字符串和字节字符串。)


2
谢谢(还有其他回复的人),我错误地认为直接转换字符直到255。 - RuiDC
2
在使用.encode(latin-1)时,我遇到了UnicodeEncodeError: 'ascii' codec can't encode characters in position 2-3: ordinal not in range(128)错误。 - Shiva

77

这是无效的UTF-8编码。该字符在ISO-Latin1中是e-acute字符,因此该编码集成功解码。

如果您不知道接收到的字符串所用的编码集,则会遇到一些麻烦。最好为您的协议/应用程序选择单个编码集(希望是UTF-8),然后拒绝无法解码的内容。

如果无法执行上述操作,则需要使用启发式方法。


4
关于启发式算法,请参考 chardet 库。 - mlissner

54

由于UTF-8是多字节的,因此没有字符与您的\xe9加上后面的空格相对应。

为什么它应该在utf-8和latin-1中都成功呢?

以下是相同句子在utf-8中的写法:

>>> o.decode('latin-1').encode("utf-8")
'a test of \xc3\xa9 char'

Latin-1是一种单字节编码系列,因此其中的所有内容都应该在UTF-8中定义。但为什么有时会使用Latin-1呢? - Reihan_amn

29

如果显示UTF-8错误,请使用此选项

pd.read_csv('File_name.csv',encoding='latin-1')

27

如果在处理刚打开的文件时出现此错误,请检查是否以'rb'模式打开它。


5
多亏这个答案,我能够避免以下错误:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd7 in position 2024079: invalid continuation byte方法是使用下面的代码:soup = BeautifulSoup(open('webpage.html', 'rb'), 'html.parser')其中,BeautifulSoup是一个Python的库,用于解析HTML和XML文档。在上述代码中,'webpage.html'是需要解析的文件名,'rb'表示以二进制模式打开文件,'html.parser'是指定使用HTML解析器进行解析。 - Isaac Philip
当使用trimesh.util.concatenate()的导出方法时,这也是解决相同问题的方法。 - x__x

21

当数字值的范围超过0到127时,通常会出现utf-8编码错误。

引发此异常的原因是:

1)如果代码点小于128,则每个字节与代码点的值相同。 2)如果代码点大于或等于128,则Unicode字符串无法用此编码表示。(在这种情况下,Python引发UnicodeEncodeError异常。)

为了克服此问题,我们有一组编码,其中最广泛使用的是“Latin-1,也称为ISO-8859-1”

所以ISO-8859-1 Unicode点0-255与Latin-1值相同,因此将其转换为此编码只需将代码点转换为字节值;如果遇到大于255的代码点,则无法将字符串编码为Latin-1。

如果在尝试加载数据集时遇到此异常,请尝试使用此格式。

df=pd.read_csv("top50.csv",encoding='ISO-8859-1')

在语法结尾处添加编码技术,从而可以接受加载数据集。


你好,欢迎来到SO!请[编辑]您的答案,以确保它比其他已经存在于这个问题中的答案更好。 - hongsy

12

当您在 Pandas 中输入特定文件或数据时,就会出现这种类型的错误,例如:

data=pd.read_csv('/kaggle/input/fertilizers-by-product-fao/FertilizersProduct.csv)

然后错误会显示为:

UnicodeDecodeError: 'utf-8'编解码器无法解码第1位的0xf4:无效的续字符

因此,可以通过添加一个参数来避免出现这种类型的错误。

data=pd.read_csv('/kaggle/input/fertilizers-by-product-fao/FertilizersProduct.csv', encoding='ISO-8859-1')

请正确格式化您的代码,点击此处了解如何操作 - rizerphe
它可以工作,但是无法从FAO数据中获取一些国家名称。 - Suat Atan PhD

11

我也遇到了同样的问题,当时我在阅读一个包含希伯来文的 .txt 文件。

我点击了 文件 -> 另存为 并将该文件保存为 UTF-8 编码。


5
TLDR: 在静默错误之前,我建议深入调查问题的来源。
当我处理大量包含其他zip文件的zip文件时,遇到了这个错误。
我的工作流程如下:
1. 读取zip文件 2. 读取子zip文件 3. 从子zip文件中读取文本
在某些时候,我会遇到上述编码错误。经过仔细检查,发现一些子zip文件错误地包含其他zip文件。将这些zip文件读取为文本后,会产生一些奇怪的字符表示,可以通过“encoding="latin-1"”来消除,但反过来会导致更严重的问题。由于我正在处理国际数据,因此认为这是编码问题并非完全愚蠢(我遇到了“0xc2: ”的问题),但最终它并不是实际的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接