Un estudio sobre la iteracion sobre un cursor

Chema Cortes py en ls-l.org
Jue Jul 14 15:59:54 CEST 2005


Estoy trabajando con el adodbapi (DB-API2), y buscaba una manera
elegante para "iterar" sobre los resultados de una query para traspasar
los datos entre bases de datos. Aunque algunos módulos ofrecen
iteradores, en la DB-API2 no existe ninguna facilidad "explícita" para
iterar. Por tanto se me había ocurrido hacer algo así:

con_ori=adodbapi.connect(DSN1)
con_des=adodbapi.connect(DSN2)

cur_ori=con.cursor()
cur_des=con.cursor()

cur_ori.execute(query1)

for res in iter(cur.fetchone,None):
   cur_des.execute(query2, res)

con_ori.close()
con_des.close()


Pensando en que daría mejor redimiento utilizar el
.fetchmany/.executemany  cambié el código a lo siguiente:

...
...
for res in iter(cur_ori.fetchmany,()):
   cur_des.executemany(query2,res)
...


Pero me encontré con el problema de que el .fetchmany, según la DB-API2,
debería devolver una secuencia vacía, sin especificar si esta secuencia
es una tupla, una lista ó el qué. Como consecuencia, no es fiable
emplear la función iter(). Además me encuentro con un fallo del
.fetchmany del adodbapi que devuelte None cuando el .arraysize es 1. Sin
poner un "testigo" fiable en iter() es muy probable que éste acabe
entrando en un bucle infinito.


Solución: emplear el 'takewhile' del 'itertools'. Así quedaría el código
final:

from itertools import takewhile
...
...

for res in takewhile(bool,iter(cur_ori.fetchmany,None)):
   cur_des.executemany(query2,res)
...


Es un iterador con una doble comprobación del resultado, pero en el
fondo funciona bastante bien.


¿Os parece muy enrevesado todo ésto?¿Véis alguna forma de hacerlo más
simple?¿Créis que vale la pena utilizar el .fetchmany/.executemany?




Más información sobre la lista de distribución Python-es