[Python-es] Buscar, leer y escribir archivos grandes con Python

Alexis Roda alexis.roda.villalonga en gmail.com
Vie Jun 3 21:19:57 CEST 2011


En/na Kiko ha escrit:

En el programa que mandaste en el primer mensaje parece implícito que la 
longitud del código es siempre de 9 caracteres. Esto hace innecesario el 
uso de rsplit o rfind.

def procesa(entrada, salida) :
     with open(entrada,'r') as input:
         with open(salida,'w') as output:
             for l in input :
                 output.write(l[-9:])

In [1]: l = "1|2011-05-20 23:08:56|122711527|OPERADOR1|HOST 
TOHOST|212454|10000|HOST CLIENTE|192630167"

In [2]: timeit l.rsplit("|", 1)[-1]
1000000 loops, best of 3: 827 ns per loop

In [3]: timeit l[l.rindex("|")+1:]
1000000 loops, best of 3: 676 ns per loop

In [4]: timeit l[l.rfind("|")+1:]
1000000 loops, best of 3: 682 ns per loop

In [5]: timeit l[-9:]
1000000 loops, best of 3: 208 ns per loop

Fíjate en que utilizar rfind (o rindex) como hacías originalmente es mas 
eficiente que utilizar rsplit. La explicación es que rsplit crea dos 
cadenas (la "mitad" izquierda y la derecha), una lista con las dos 
cadenas y finalmente accede al último elemento de la lista. En la 
versión con rindex se crea directamente la cadena derecha.

Como curiosidad, en el caso de utilizar un método de l podrías arañar 
unos nanosegundos haciendo algo como:

In [6]: rf=l.rfind

In [7]: timeit l[rf("|")+1:]
1000000 loops, best of 3: 602 ns per loop

con esto evitas que el interprete tenga que buscar el método rfind de l 
en cada iteración.

> Claramente, rsplit parece que funciona mejor.  He hecho mi función
> (abrekiko) con una list comprehesion y también va un poquito más lenta 
> que con el for a pelo y tenía entendido que usar list comprehensions era 
> más efectivo.

Las list comprehension sirven para crear listas. Lo que hace tu código 
es equivalente a:

def abrelasi(entrada,salida):
     lista = []
     with open(entrada,'r') as input:
         with open(salida,'w') as output:
             for l in input :
                 lista.append(output.write(l.rsplit(',',1)[-1]))

Al final "lista" contiene 300000 valores None. No le veo el sentido.

> ¿Alguien tiene formas más rápidas de lectura de ficheros de texto?

Yo hubiese utilizado cut -d\| -f9 entrada.txt > salida.txt

Como ya te han dicho debes considerar el tiempo de desarrollo mas el 
tiempo de ejecución y valorar si el esfuerzo extra vale la pena. Dicho 
esto, si quieres aprender, te recomendaría probar el módulo cProfile:

   http://docs.python.org/library/profile.html#module-cProfile

este modulo mide el tiempo de ejecución del programa y te ayudará a 
descubrir donde está el cuello de botella. Tal vez estés dedicando horas 
a optimizar algo que luego no tiene un impacto decisivo en el tiempo 
total de ejecución.

En el caso de procesar el archivo tengo la impresión de que el problema 
estará en la E/S y no el el procesamiento de los datos en si (utilizando 
un programa razonable).



Saludos


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