我的.py文件中的这一行给了我一个:“UnicodeDecodeError:'utf8'编解码器无法解码位置8-13中的字节:不支持的Unicode代码范围”
if line.startswith(u"Fußnote"):
该文件以utf-8保存,编码位于顶部: # - - 编码:utf-8 - -
我在注释和数组中有很多其他py文件,其中包含utf-8编码的中文文本,例如:arr = [u“chinese text”,]所以我想知道为什么这个案例在特别是对我不起作用。
答案 0 :(得分:10)
让我们仔细检查一下错误信息:
“UnicodeDecodeError:'utf8'编解码器无法解码位置8-13中的字节:不支持的Unicode代码范围”
请注意,它说“8-13位的字节” - 这是一个 6字节的UTF-8序列。这可能在黑暗时代有效,但因为Unicode被冻结在21位,最大值是四个字节。 UTF-8验证和错误报告were tightened up recently;感兴趣的是,你正在运行什么版本的Python?
至少使用2.7.1和2.6.6,该错误变得更有用“......无法解码位置8中的字节XXXX:无效的起始字节”,其中XXXX只能是0xfc或0xfd,如果旧的消息建议一个6字节的序列。在ISO-8859-1或cp1252中,0xfc表示带有DIAERESIS的U + 00FC LATIN SMALL LETTER U(又名u-umlaut,可能是嫌疑人); 0xfd代表U + 00FD LATIN小写字母Y与急性(不太可能)。
问题不在于源文件中的if line.startswith(u"Fußnote"):
语句。如果它不是正确的UTF-8,你会在COMPILE时收到一条消息,并且消息将以“SyntaxError”开头,而不是“UnicodeDecodeError”。在任何情况下,该字符串的UTF-8编码只有8个字节长,而不是14个字节。
问题是(正如@Mark Tolonen指出的那样)无论“行”指的是什么。它只能是一个str对象。
为了更进一步,您需要回答Mark的问题(1)print repr(line)
(2)site.py
更改的结果。
在这个阶段,最好清除混合str
和unicode
对象的空气(在许多操作中,而不仅仅是a.startswith(b)
)。
除非定义操作以生成str
对象,否则它不会将unicode
对象强制转换为str
。 {{em>}不是这种情况。 {1}}。它将尝试使用默认(通常为“ascii”)编码对a.startswith(b)
对象进行解码。
示例:
str
此外,说“混合你得到UnicodeDecodeError”是不正确的。 >>> "\xff".startswith(u"\xab")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)
>>> u"\xff".startswith("\xab")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xab in position 0: ordinal not in range(128)
对象很可能是以默认编码有效编码的(通常是'ascii') ) - 没有例外。
示例:
str
答案 1 :(得分:6)
我可以使用以下代码重现UnicodeDecodeError:
#!/usr/bin/env python
# -- coding: utf-8 --
line='Fußnoteno'
if line.startswith(u"Fußnote"):
print('Hi')
请注意,line
是一个字符串对象,但u"Fußnote"
是一个unicode对象。
由于line
是一个字符串对象,因此在调用startswith
时,unicode对象将转换为字符串对象。在Python2中,默认是尝试使用ascii编解码器进行解码。
由于无法使用ascii编解码器解码u"ß"
,因此会引发UnicodeDecodeError。
如果您首先使line
成为unicode对象,则可以避免错误:
line='Fußnoteno'.decode('utf-8')
if line.startswith(u"Fußnote"):
print('Hi')
或者如果您首先使u"Fußnote"
成为字符串对象:
line='Fußnoteno'
if line.startswith(u"Fußnote".encode('utf-8')):
print('Hi')
答案 2 :(得分:3)
错误表明 line 不是Unicode字符串。在X.startswith(Y)
中,X和Y都必须是Unicode或字节串。混合,你得到UnicodeDecodeError。 print repr(line)
检查它。您是否也更改了site.py
以将默认编码从“ascii”更改为“utf8”?通常情况下,'ascii'编解码器是Python 2.x的默认编码。
答案 3 :(得分:2)
如果没有看到您的代码,则不清楚问题是代码或代码正在读取的数据文件。
当你打开文件时,你在做什么:
file = open("essay.txt")
或:
import codecs
file = codecs.open("essay.txt", encoding="utf-8")
做什么:
print file.encoding
如果您将其添加到open
行的下方?
这两种方式对我有用:
# -- coding: utf-8 --
file = open("essay.txt")
print file.encoding
for line in file:
uline = line.decode("utf-8")
print type(uline)
if uline.startswith(u"Fußnote"):
print "Footnote"
else:
print "Other"
这样:
# -- coding: utf-8 --
import codecs
file = codecs.open("essay.txt", encoding="utf-8")
print file.encoding
for line in file:
print type(line)
if line.startswith(u"Fußnote"):
print "Footnote"
else:
print "Other"
在第一个中,我让Python默认将文件作为字节流打开,然后使用uline = line.decode("utf-8")
将每行从字节流转换为Unicode字符串。
在第二个中,我将文件作为UTF-8编码文件打开,因此Python在迭代文件时返回Unicode字符串。
修改强>
这是一种简单的方法,可以用来确定文件是否包含任何非utf8数据。
import codecs
file = open("baduni.txt")
try:
for char in codecs.iterdecode(file, "utf-8"):
print char
except UnicodeDecodeError as e:
print "error:", e
使用它的一个例子:
$ echo 'ABC\0200\0101DEF' > baduni.txt
$ od -c baduni.txt
0000000 A B C 200 A D E F \n
0000011
$ python testuni.py
error: 'utf8' codec can't decode byte 0x80 in position 3: invalid start byte
在该示例中,第4个字节(位置3,从0开始计数)为200
八进制/ 0x80
十六进制。
The Wikipedia UTF-8 article表明这只会作为双字节序列的第二个字节有效。
答案 4 :(得分:0)
您的文件以其他一些编码保存,而不是 UTF-8。弄清楚文件的编码方式(可能是CP1252左右),然后再声明。