(0) Vous avez demandé "Pourquoi win32com est-il plus lent que xlrd?" ... cette question est un peu comme "Avez-vous arrêté de battre votre femme?" --- il est basé sur une présupposition qui peut ne pas être vraie; win32com a été écrit en C par un brillant programmeur, mais xlrd a été écrit en pur Python par un programmeur moyen. La vraie différence est que win32com doit appeler COM qui implique une communication inter-processus et a été écrit par you-know-who, alors que xlrd lit directement le fichier Excel. De plus, il y a une quatrième partie dans le scénario: VOUS. S'il vous plaît lisez la suite.
(1) Vous ne nous montrez pas la source de la fonction find_last_col()
que vous utilisez répétitivement dans le code COM. Dans le code xlrd, vous êtes heureux d'utiliser la même valeur (ws.ncols) tout le temps. Donc, dans le code COM, vous devez appeler find_last_col(ws)
une fois et ensuite utilisé le résultat retourné. Mise à jour Voir answer to your separate question sur la façon d'obtenir l'équivalent de Sheet.ncols
de xlrd de COM. (2) L'accès à chaque valeur de cellule TWICE ralentit les deux codes. Au lieu de
if ws.cell_value(6, cnum):
wsHeaders[str(ws.cell_value(6, cnum))] = (cnum, ws.ncols)
essayer
value = ws.cell_value(6, cnum)
if value:
wsHeaders[str(value)] = (cnum, ws.ncols)
Note: il y a 2 cas de ce dans chaque extrait de code.
(3) Il n'est pas du tout évident quel est le but de vos boucles imbriquées, mais il semble y avoir des calculs redondants, impliquant des extractions redondantes de COM. Si vous voulez nous dire ce que vous essayez de réaliser, avec des exemples, nous pourrions vous aider à le faire fonctionner plus rapidement. À tout le moins, extraire les valeurs de COM une fois puis les traiter dans des boucles imbriquées dans Python devrait être plus rapide. Combien de colonnes y a-t-il?
Update 2 Pendant ce temps les petits lutins ont pris à votre code avec le proctoscope, et sont venus avec le script suivant:
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
qui sort ceci:
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 Je suis d'accord - le ralentissement n'est pas dû à COM mais à cause de l'utilisation de l'OP qui le rend plus lent. – Cam
Il existe également des moyens de lire et d'écrire plusieurs valeurs depuis/vers Excel à l'aide de COM via safearrays, précisément en raison du surdébit IPC.Vous pouvez le faire de manière transparente via win32com, en spécifiant des plages au lieu de cellules individuelles. –