UnicodeEncodeError:'ascii'编解码器无法编码字符u'\ xa3'

AP2*_*257 22 python character-encoding

我有一个Excel电子表格,我正在阅读其中包含一些£符号.

当我尝试使用xlrd模块读取它时,我收到以下错误:

x = table.cell_value(row, col)
x = x.decode("ISO-8859-1")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa3' in position 0: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)

如果我将其重写为x.encode('utf-8'),它会停止抛出错误,但不幸的是,当我将数据写入其他地方时(如latin-1),£符号都变得乱码.

我该如何解决这个问题,并正确阅读英镑符号?

---更新---

某些读者建议我根本不需要解码它,或者我可以在需要时将其编码为Latin-1.这个问题是我最终需要将数据写入CSV文件,它似乎反对原始字符串.

如果我根本不对数据进行编码或解码,则会发生这种情况(在我将字符串添加到名为items的数组之后):

for item in items:
    #item = [x.encode('latin-1') for x in item]
    cleancsv.writerow(item)
File "clean_up_barnet.py", line 104, in <module>
 cleancsv.writerow(item)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2022' in position 43: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)

即使我取消注释Latin-1行,我也会得到相同的错误.

jtu*_*ull 19

围绕所有"'ascii'编解码器无法编码字符..."的一个非常简单的方法csvwriter的问题是使用unicodecsv,csvwriter的替代品.

使用pip安装unicodecsv然后你可以以完全相同的方式使用它,例如:

import unicodecsv
file = open('users.csv', 'w')
w = unicodecsv.writer(file)
for user in User.objects.all().values_list('first_name', 'last_name', 'email', 'last_login'):
    w.writerow(user)
Run Code Online (Sandbox Code Playgroud)


Joh*_*hin 10

值得的是:我是作者xlrd.

xlrd产生unicode吗?
选项1:阅读第一个xlrddoc 屏幕底部的Unicode部分:该模块将所有文本字符串显示为Python unicode对象.
选项2:print type(text), repr(text)

你说""如果我把它重写为x.encode('utf-8')它就会停止抛出一个错误,但不幸的是当我把数据写到其他地方时(如latin-1),£符号都变成了当然,如果你把UTF-8编码的文本写入一个期望latin1的设备,它将会出现乱码.你有什么期望?

你在你的编辑中说:"""即使我取消注释Latin-1行"""我也会得到同样的错误.这是非常不可能的 - 更有可能的是你在不同的源代码行(未注释的latin1行而不是writerow行)中出现了稍微不同的错误(提到latin1编解码器而不是ascii编解码器).仔细阅读错误消息有助于理解.

你的问题是,一般来说你的数据不能用latin1编码; 现实世界的数据很少.你的POUND SIGN可以在latin1中编码,但这不是你所有的非ASCII数据.有问题的角色是U + 2022 BULLET,在latin1中无法编码.

如果您事先提到过在Mac OS X上工作,那么它会帮助您尽快得到更好的答案......对于适合CSV的编码通常是怀疑cp1252(Windows),而不是mac-roman.


Ale*_*lli 9

你的代码片段说x.decode,但你得到一个编码错误 - 意味着x已经是Unicode,所以,为了"解码"它,它必须首先变成一个字节串(这是默认编解码器ansi出现并失败的地方) .在你的文本,然后你说:"如果我重写OT对x.编码 " ......这似乎意味着,你知道X是Unicode.

那么你正在做什么 - 以及你的意思是做什么 - 编码一个unicode x来获得一个编码的字节串,或者将一串字节解码成一个unicode对象?

我发现不幸的是你可以调用encode一个字节字符串,并且decode在一个unicode对象上,因为我发现它似乎引导用户除了混乱......但至少在这种情况下你似乎设法传播混乱(在对我来说最少;-).

如果,似乎x是unicode,那么你永远不想"解码"它 - 你可能想要编码它以获得带有某个编解码器的字节串,例如latin-1,如果这是你需要某种类型的I/O目的(对于您自己的内部程序使用,我建议始终坚持使用unicode - 只有在您绝对需要接收编码字节字符串时才进行编码/解码以进行输入/输出).


dan*_*n04 5

x = x.decode("ISO-8859-1")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa3' in position 0: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)

仔细观察:你有一个Unicode***编码***错误调用解码方法.

原因是它decode旨在从字节序列(str)转换为unicode对象.但是,正如约翰所说,xlrd已经使用了Unicode字符串,因此x已经是一个unicode对象.

在这种情况下,Python的2.x的假定您的意思来解码str对象,因此它"有益"为您创建一个.但是为了将a转换unicode为a str,它需要编码,并选择ASCII,因为它是字符编码的最低公分母.您的代码有效地被解释为

x = x.encode('ascii').decode("ISO-8859-1")
Run Code Online (Sandbox Code Playgroud)

失败,因为x包含非ASCII字符.

既然x已经是一个unicode对象,那decode就没必要了.但是,现在您遇到了Python 2.x csv模块不支持Unicode的问题.您必须将数据转换为str对象.

for item in items:
    item = [x.encode('latin-1') for x in item]
    cleancsv.writerow(item)
Run Code Online (Sandbox Code Playgroud)

这是正确的,除了你的数据中有字符(U + 2022 BULLET),而Latin-1不能代表它.有几种方法可以解决这个问题:

  • 写入x.encode('latin-1', 'ignore')删除子弹(或其他非拉丁字符1).
  • 写下x.encode('latin-1', 'replace')用问号替换子弹.
  • 用像*或的Latin-1字符替换子弹·.
  • 使用字符编码包含所有你需要的字符.

目前,UTF-8得到广泛支持,因此几乎没有理由对文本文件使用任何其他编码.