(0)您问“为什么win32com比xlrd慢得多?” ......这个问题有点像“你不再殴打你的妻子吗?” ---它是基于一个可能不是真的假设; win32com由一位出色的程序员用C语言编写,但是xlrd是由普通程序员用纯Python编写的。真正的区别在于win32com必须调用COM,其中涉及进程间通信和由you-know-who编写,而xlrd则直接读取Excel文件。此外,场景中还有第四方:您。请继续阅读。
(1)您不会向我们展示在COM代码中重复使用的find_last_col()
函数的来源。在xlrd代码中,您总是乐意使用相同的值(ws.ncols)。所以在COM代码中,你应该调用find_last_col(ws)
ONCE,然后使用返回的结果。 更新请参阅answer to your separate question关于如何从COM获取xlrd的Sheet.ncols
的等效项。 (2)访问每个单元值TWICE正在减慢两个代码的速度。取而代之的
if ws.cell_value(6, cnum):
wsHeaders[str(ws.cell_value(6, cnum))] = (cnum, ws.ncols)
尝试
value = ws.cell_value(6, cnum)
if value:
wsHeaders[str(value)] = (cnum, ws.ncols)
注:有每个代码片断2案件这一点。
(3)你的嵌套循环的目的并不明显,但似乎有一些冗余计算,涉及从COM冗余提取。如果你想通过例子告诉我们你想要达到的目标,我们可以帮助你使其运行得更快。至少,从COM中提取值然后在Python中嵌套循环中处理它们应该更快。有多少列?
更新2同时,小精灵走上与直肠镜你的代码,并与下面的脚本上来:
tests= [
"A/B/C/D",
"A//C//",
"A//C//E",
"A///D",
"///D",
]
for test in tests:
print "\nTest:", test
row = test.split("/")
ncols = len(row)
# modelling the OP's code
# (using xlrd-style 0-relative column indexes)
d = {}
for cnum in xrange(ncols):
if row[cnum]:
k = row[cnum]
v = (cnum, ncols) #### BUG; should be ncols - 1 ("inclusive")
print "outer", cnum, k, '=>', v
d[k] = v
for cend in xrange(cnum + 1, ncols):
if row[cend]:
k = row[cnum]
v = (cnum, cend - 1)
print "inner", cnum, cend, k, '=>', v
d[k] = v
break
print d
# modelling a slightly better algorithm
d = {}
prev = None
for cnum in xrange(ncols):
key = row[cnum]
if key:
d[key] = [cnum, cnum]
prev = key
elif prev:
d[prev][1] = cnum
print d
# if tuples are really needed (can't imagine why)
for k in d:
d[k] = tuple(d[k])
print d
它输出这样的:因为它
Test: A/B/C/D
outer 0 A => (0, 4)
inner 0 1 A => (0, 0)
outer 1 B => (1, 4)
inner 1 2 B => (1, 1)
outer 2 C => (2, 4)
inner 2 3 C => (2, 2)
outer 3 D => (3, 4)
{'A': (0, 0), 'C': (2, 2), 'B': (1, 1), 'D': (3, 4)}
{'A': [0, 0], 'C': [2, 2], 'B': [1, 1], 'D': [3, 3]}
{'A': (0, 0), 'C': (2, 2), 'B': (1, 1), 'D': (3, 3)}
Test: A//C//
outer 0 A => (0, 5)
inner 0 2 A => (0, 1)
outer 2 C => (2, 5)
{'A': (0, 1), 'C': (2, 5)}
{'A': [0, 1], 'C': [2, 4]}
{'A': (0, 1), 'C': (2, 4)}
Test: A//C//E
outer 0 A => (0, 5)
inner 0 2 A => (0, 1)
outer 2 C => (2, 5)
inner 2 4 C => (2, 3)
outer 4 E => (4, 5)
{'A': (0, 1), 'C': (2, 3), 'E': (4, 5)}
{'A': [0, 1], 'C': [2, 3], 'E': [4, 4]}
{'A': (0, 1), 'C': (2, 3), 'E': (4, 4)}
Test: A///D
outer 0 A => (0, 4)
inner 0 3 A => (0, 2)
outer 3 D => (3, 4)
{'A': (0, 2), 'D': (3, 4)}
{'A': [0, 2], 'D': [3, 3]}
{'A': (0, 2), 'D': (3, 3)}
Test: ///D
outer 3 D => (3, 4)
{'D': (3, 4)}
{'D': [3, 3]}
{'D': (3, 3)}
+1我同意 - 放缓不是因为COM,而是因为OP的使用,使得它看起来更慢。 – Cam 2010-06-04 01:55:36
正是由于IPC的开销,还有许多方法可以使用COM通过安全数组读取和写入多个值。你可以通过win32com透明地做到这一点,通过指定范围而不是单个单元。 – 2010-06-04 03:38:46