我在我的.py文件中遇到了这个问题:"UnicodeDecodeError: 'utf8'编解码器无法解码第8-13位字节:不支持的Unicode代码范围"
if line.startswith(u"Fußnote"):
该文件以utf-8编码保存,编码位于文件顶部: # -- coding: utf-8 --
我有许多其他py文件,其中包含utf-8编码的中文文本,例如在注释和数组中:arr = [u"chinese text",],所以我想知道为什么特定情况下我的代码无法工作。
让我们仔细检查一下这个错误信息:
"UnicodeDecodeError: 'utf8'编解码器无法解码第8-13个字节: 不支持的Unicode代码范围"
请注意,它说"第8-13个字节"——那是一个6字节UTF-8序列。在古老的时代可能有效,但自Unicode在21位时被冻结后,最大长度为四个字节。UTF-8验证和错误报告最近已经得到加强; 顺便问一下,你正在运行哪个版本的Python?
至少在2.7.1和2.6.6中,该错误变得更有用:"... can't decode byte XXXX in position 8: invalid start byte",其中XXXX只能是0xfc或0xfd,如果旧消息建议6字节序列。在ISO-8859-1或cp1252中,0xfc表示U+00FC LATIN SMALL LETTER U WITH DIAERESIS(也称为u-umlaut,是一个可能的嫌疑人);0xfd表示U+00FD LATIN SMALL LETTER Y WITH ACUTE(不太可能)。
问题并不在于源文件中的if line.startswith(u"Fußnote"):
语句。如果它不是正确的UTF-8,您会在编译时收到一条消息,并且该消息将以"SyntaxError"而不是"UnicodeDecodeError"开头。无论如何,该字符串的UTF-8编码只有8个字节长,而不是14个。
问题在于(正如@Mark Tolonen指出的那样)"line"所指的内容。它只能是一个str对象。
为了进一步学习,您需要回答Mark的问题(1)print repr(line)
的结果是什么,(2)site.py
的更改。
在这个阶段,清楚混合使用str
和unicode
对象的情况是一个好主意(在许多操作中,不仅仅是a.startswith(b)
)。
除非操作被定义为生成str
对象,否则它不会强制将unicode
对象转换为str
。 这对于a.startswith(b)
来说并不适用。 它将尝试使用默认编码(通常是“ascii”)解码str
对象。
例子:
>>> "\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)
str
对象很可能已经使用默认编码(通常为'ascii')进行了正确编码,因此不会引发异常。>>> "abc".startswith(u"\xff")
False
>>> u"\xff".startswith("abc")
False
>>>
#!/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 编解码器进行解码。
由于 u"ß"
无法使用 ascii 编解码器进行解码,因此会引发 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')
str
]对象。请参阅我的答案。 - John MachinX.startswith(Y)
中,X和Y必须是Unicode或字节串。如果混合使用,则会出现UnicodeDecodeError错误。请使用print repr(line)
检查它。另外,您是否已更改site.py
以将默认编码从'ascii'更改为'utf8'?通常情况下,Python 2.x的默认编解码器是'ascii'。没有看到你的代码,无法确定问题是代码还是代码读取的数据文件。
当你打开文件时,你是这样做的吗:
file = open("essay.txt")
或者:
import codecs
file = codecs.open("essay.txt", encoding="utf-8")
What does:
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"
uline=line.decode("utf-8")
将每行从字节流转换为Unicode字符串。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
200
或十六进制0x80
。维基百科UTF-8文章显示这只能作为一个两字节序列的第二个字节有效。你的文件保存在其他编码格式中,而不是UTF-8。找出文件所使用的编码格式(可能是CP1252或其他),并声明该编码格式。
od -t c
。 - Raph Levienhexdump -C
пјЊиЂЊFreeBSDе€™жњ‰hd(1)
гЂ‚ - YasirA