¿Cómo leer un archivo CSV de una transmisión y procesar cada línea a medida que se escribe?

Me gustaría leer un archivo CSV de la entrada estándar y procesar cada fila como corresponda. El código de salida de CSV escribe las filas una por una, pero mi lector espera que la secuencia finalice antes de iterar las filas. ¿Es esta una limitación del módulo csv ? ¿Estoy haciendo algo mal?

Mi código de lector:

 import csv import sys import time reader = csv.reader(sys.stdin) for row in reader: print "Read: (%s) %r" % (time.time(), row) 

Mi código de escritor:

 import csv import sys import time writer = csv.writer(sys.stdout) for i in range(8): writer.writerow(["R%d" % i, "$" * (i+1)]) sys.stdout.flush() time.sleep(0.5) 

Salida de python test_writer.py | python test_reader.py python test_writer.py | python test_reader.py :

 Read: (1309597426.3) ['R0', '$'] Read: (1309597426.3) ['R1', '$$'] Read: (1309597426.3) ['R2', '$$$'] Read: (1309597426.3) ['R3', '$$$$'] Read: (1309597426.3) ['R4', '$$$$$'] Read: (1309597426.3) ['R5', '$$$$$$'] Read: (1309597426.3) ['R6', '$$$$$$$'] Read: (1309597426.3) ['R7', '$$$$$$$$'] 

Como puede ver, todas las declaraciones de impresión se ejecutan al mismo tiempo, pero espero que haya un espacio de 500 ms.

Como se dice en la documentación ,

Para hacer que un bucle for la forma más eficiente de realizar un bucle en las líneas de un archivo (una operación muy común), el método next() utiliza un búfer de lectura anticipada oculto.

Y puede ver al observar la implementación del módulo csv (línea 784) que csv.reader llama al método next() del iterador de underlyling (a través de PyIter_Next ).

Por lo tanto, si realmente desea leer los archivos CSV sin búfer, debe convertir el objeto de archivo (aquí sys.stdin ) en un iterador cuyo método next() realidad llama a readline() . Esto se puede hacer fácilmente usando la forma de dos argumentos de la función iter . Así que cambia el código en test_reader.py a algo como esto:

 for row in csv.reader(iter(sys.stdin.readline, '')): print("Read: ({}) {!r}".format(time.time(), row)) 

Por ejemplo,

 $ python test_writer.py | python test_reader.py Read: (1388776652.964925) ['R0', '$'] Read: (1388776653.466134) ['R1', '$$'] Read: (1388776653.967327) ['R2', '$$$'] Read: (1388776654.468532) ['R3', '$$$$'] [etc] 

¿Puede explicar por qué necesita la lectura no almacenada de archivos CSV? Podría haber una mejor solución para lo que sea que esté tratando de hacer.

Tal vez sea una limitación. Lea este http://docs.python.org/using/cmdline.html#cmdoption-unittest-discover-u

Tenga en cuenta que hay un búfer interno en file.readlines () y File Objects (para la línea en sys.stdin) que no está influenciado por esta opción. Para solucionar esto, querrá usar file.readline () dentro de un bucle de while 1 :.

He modificado test_reader.py de la siguiente manera:

 import csv, sys, time while True: print "Read: (%s) %r" % (time.time(), sys.stdin.readline()) 

Salida

 python test_writer.py | python test_reader.py Read: (1309600865.84) 'R0,$\r\n' Read: (1309600865.84) 'R1,$$\r\n' Read: (1309600866.34) 'R2,$$$\r\n' Read: (1309600866.84) 'R3,$$$$\r\n' Read: (1309600867.34) 'R4,$$$$$\r\n' Read: (1309600867.84) 'R5,$$$$$$\r\n' Read: (1309600868.34) 'R6,$$$$$$$\r\n' Read: (1309600868.84) 'R7,$$$$$$$$\r\n' 

Estás limpiando stdout, pero no stdin.

Sys.stdin también tiene un método flush() , intente usarlo después de cada línea leída si realmente desea deshabilitar el búfer.