在我的python文件中写入utf-8字符串

时间:2011-01-27 02:43:27

标签: python unicode utf-8

我的.py文件中的这一行给了我一个:“UnicodeDecodeError:'utf8'编解码器无法解码位置8-13中的字节:不支持的Unicode代码范围”

if line.startswith(u"Fußnote"):

该文件以utf-8保存,编码位于顶部: # - - 编码:utf-8 - -

我在注释和数组中有很多其他py文件,其中包含utf-8编码的中文文本,例如:arr = [u“chinese text”,]所以我想知道为什么这个案例在特别是对我不起作用。

5 个答案:

答案 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更改的结果。

在这个阶段,最好清除混合strunicode对象的空气(在许多操作中,而不仅仅是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左右),然后再声明。