ans*_*ung 18 python csv unicode encoding xlrd
我正在尝试使用Python xlrd和csv模块将Excel电子表格翻译为CSV,但我对编码问题感到困惑.Xlrd以Unicode格式生成Excel中的输出,CSV模块需要UTF-8.
我想象这与xlrd模块无关:一切正常输出到stdout或其他不需要特定编码的输出.
根据,工作表编码为UTF-16-LE book.encoding
我正在做的简化版本是:
from xlrd import *
import csv
b = open_workbook('file.xls')
s = b.sheet_by_name('Export')
bc = open('file.csv','w')
bcw = csv.writer(bc,csv.excel,b.encoding)
for row in range(s.nrows):
this_row = []
for col in range(s.ncols):
this_row.append(s.cell_value(row,col))
bcw.writerow(this_row)
Run Code Online (Sandbox Code Playgroud)
这会产生以下错误,大约740行:
UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 5: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)
似乎挂起的值是"516-777316" - 原始Excel工作表中的文本是"516-7773167"(最后有7个)
我会是第一个承认,我只有字符编码是如何工作的一个模糊的感觉,所以大部分是我到目前为止已经试过是各种摸索排列.encode,并.decode在s.cell_value(row,col)
如果有人可以建议一个解决方案我会很感激 - 如果你能解释一下什么不起作用以及为什么这样做会更好,那么我将来可以更容易地调试这些问题.
提前致谢!
编辑:
感谢您的评论到目前为止.
当我用户this_row.append(s.cell(row,col))(egscell而不是s.cell_value)时,整个文档写入没有错误.
输出并不是特别理想的(text:u'516-7773167'),但它避免了错误,即使有问题的字符仍然在输出中.
这让我觉得挑战可能毕竟是xlrd.
思考?
Ale*_*lli 25
我希望cell_value返回值是unicode字符串,它会给你带来问题(请打印type()确认),在这种情况下你应该能够通过改变这一行来解决它:
this_row.append(s.cell_value(row,col))
Run Code Online (Sandbox Code Playgroud)
至:
this_row.append(s.cell_value(row,col).encode('utf8'))
Run Code Online (Sandbox Code Playgroud)
如果cell_value返回多个不同的类型,那么当且仅当它返回一个unicode字符串时,你需要编码; 所以你将这一行分成几行:
val = s.cell_value(row, col)
if isinstance(val, unicode):
val = val.encode('utf8')
this_row.append(val)
Run Code Online (Sandbox Code Playgroud)
你要求解释,但如果没有你的帮助,有些现象是莫名其妙的.
(A)由Excel 97以后创建的XLS文件中的字符串以Latin1编码,否则以UTF16LE编码.每个字符串都带有一个标志,告诉哪个被使用 早期Excel根据用户的"代码页"编码字符串.在任何情况下,xlrd都会生成unicode对象.仅当第三方软件创建了XLS文件时,文件编码才会引起关注,第三方软件要么省略代码页,要么就是代码页.请参阅xlrd文档前面的Unicode部分.
(B)原因不明的现象:
这段代码:
bcw = csv.writer(bc,csv.excel,b.encoding)
Run Code Online (Sandbox Code Playgroud)
使用Python TypeError: expected at most 2 arguments, got 32.5,2.6 和3.1导致以下错误:- 这是关于csv.writer上的文档我期望的; 它期待一个类似文件的对象,后跟(1)没有(2)方言或(3)一个或多个格式化参数.你给它一个方言,而csv.writer没有编码参数,所以splat.您使用的是哪个版本的Python?或者你没有复制/粘贴你实际运行的脚本?
(C)回溯周围无法解释的现象以及实际的违规数据:
"the_script.py", line 40, in <module>
this_row.append(str(s.cell_value(row,col)))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xed' in position 5: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)
首先,在违规代码行中有一个不在简化脚本中的str() - 你没有复制/粘贴你实际运行的脚本吗?在任何情况下,你都不应该使用str - 你不会得到你的花车的全部精度; 让csv模块转换它们.
第二,你说""这个价值似乎被挂起了"516-777316" - 原始Excel表格中的文字是"516-7773167"(最后有7个)""" - - 很难想象7如何在最后丢失.我会使用这样的东西来确切地找出有问题的数据:
try:
str_value = str(s.cell_value(row, col))
except:
print "row=%d col=%d cell_value=%r" % (row, col, s.cell_value(row, col))
raise
Run Code Online (Sandbox Code Playgroud)
%r使您免于键入cell_value=%s ... repr(s.cell_value(row, col))... repr()生成数据的明确表示.学习它.用它.
你是怎么到达"516-777316"的?
第三,错误信息实际上是抱怨偏移5处的unicode字符u'\ xed'(即第六个字符).U + 00ED是拉丁文的小写字母,我很敏感,在"516-7773167"中根本就没有这样的东西
第四,错误位置似乎是一个移动目标 - 你在其中一个解决方案的评论中说:"错误在bcw.writerow上." 咦?
(D)为什么你得到了这个错误消息(使用str()):str(a_unicode_object)尝试将unicode对象转换为str对象,并且在没有任何编码信息的情况下使用ascii,但是你有非ascii数据,所以splat.请注意,您的对象是生成以utf8编码的csv文件,但您的简化脚本未在任何地方提及utf8.
(E)"""... s.cell(row,col))(egscell而不是s.cell_value)整个文档写入没有错误.输出不是特别需要(文本:u'516-7773167')"""
这种情况正在发生,因为csv编写器正在调用__str__Cell对象的方法,这会产生<type>:<repr(value)>可能对调试有用但正如你在csv文件中说的那么好.
(F)Alex Martelli的解决方案很棒,因为它让你前进.但是,您应该阅读xlrd docs中Cell类的部分:单元格的类型是text,number,boolean,date,error,blank和empty.如果你有日期,你会想要将它们格式化为日期而不是数字,所以你不能使用isinstance()(你可能不希望函数调用开销)...这就是Cell.ctype属性Sheet.cell_type()和Sheet.row_types()方法是给.
(G)UTF8不是Unicode.UTF16LE不是Unicode.UTF16不是Unicode ...并且单个字符串在UTF16 BOM上每个浪费2个字节的想法对于即使是MS来说也是荒谬的:-)
(H)进一步阅读(除xlrd文档外):
http://www.joelonsoftware.com/articles/Unicode.html
http://www.amk.ca/python/howto/unicode
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24956 次 |
| 最近记录: |