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.
你的代码片段说x.decode,但你得到一个编码错误 - 意味着x已经是Unicode,所以,为了"解码"它,它必须首先变成一个字节串(这是默认编解码器ansi出现并失败的地方) .在你的文本,然后你说:"如果我重写OT对x.编码 " ......这似乎意味着,你不知道X是Unicode.
那么你正在做什么 - 以及你的意思是做什么 - 编码一个unicode x来获得一个编码的字节串,或者将一串字节解码成一个unicode对象?
我发现不幸的是你可以调用encode一个字节字符串,并且decode在一个unicode对象上,因为我发现它似乎引导用户除了混乱......但至少在这种情况下你似乎设法传播混乱(在对我来说最少;-).
如果,似乎x是unicode,那么你永远不想"解码"它 - 你可能想要编码它以获得带有某个编解码器的字节串,例如latin-1,如果这是你需要某种类型的I/O目的(对于您自己的内部程序使用,我建议始终坚持使用unicode - 只有在您绝对需要或接收编码字节字符串时才进行编码/解码以进行输入/输出).
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得到广泛支持,因此几乎没有理由对文本文件使用任何其他编码.
| 归档时间: |
|
| 查看次数: |
43799 次 |
| 最近记录: |