Usando el módulo csv de Python al actualizar el archivo

Estoy utilizando el módulo csv de python para extraer datos de un csv que se actualiza constantemente mediante una herramienta externa. Me he encontrado con un problema en el que, cuando llego al final del archivo, aparece un error StopIteration; sin embargo, deseo que el script continúe en bucle esperando que la herramienta externa agregue más líneas.

Lo que se me ocurrió hasta ahora para hacer esto es:

f = open('file.csv') csvReader = csv.reader(f, delimiter=',') while 1: try: doStuff(csvReader.next()) except StopIteration: depth = f.tell() f.close() f = open('file.csv') f.seek(depth) csvReader = csv.reader(f, delimiter=',') 

Esto tiene la funcionalidad deseada pero también parece terrible. No es posible realizar un bucle después de capturar la StopIteration, ya que una vez que se lanza StopIteration, lanzará una StopIteration en cada llamada subsiguiente a next (). ¿Alguien tiene alguna sugerencia sobre cómo implementar esto es de tal manera que no tenga que hacer esta tontería y búsqueda? O bien, tenga un módulo Python diferente que pueda admitir fácilmente esta funcionalidad.

Su problema no es con el lector CSV, sino con el objeto de archivo en sí. Es posible que aún tenga que hacer los giros locos que está haciendo en su fragmento de código anterior, pero sería mejor crear un objeto objeto de archivo o subclase que lo haga por usted, y usarlo con su lector de CSV. Eso mantiene la complejidad aislada de su código de procesamiento csv.

Por ejemplo (advertencia: código no probado):

 class ReopeningFile(object): def __init__(self, filename): self.filename = filename self.f = open(self.filename) def next(self): try: self.f.next() except StopIteration: depth = self.f.tell() self.f.close() self.f = open(self.filename) self.f.seek(depth) # May need to sleep here to allow more data to come in # Also may need a way to signal a real StopIteration self.next() def __iter__(self): return self 

Luego, su código principal se vuelve más simple, ya que se libera de tener que administrar la reapertura del archivo (tenga en cuenta que también no tiene que reiniciar su csv_reader cada vez que se reinicia el archivo:

 import csv csv_reader = csv.reader(ReopeningFile('data.csv')) for each in csv_reader: process_csv_line(each) 

Las cosas productor-consumidor pueden ser un poco complicadas. ¿Qué hay de usar buscar y leer bytes en su lugar? ¿Qué pasa con el uso de una tubería con nombre?

Heck, ¿por qué no comunicarse a través de un socket local?

Rara vez necesita capturar StopIteration explícitamente. Hacer esto:

 for row in csvReader: doStuff(row) 

Para detectar cuándo se escriben nuevas líneas en el archivo, puede abrir un proceso tail -f o escribir el código de Python para determinar qué hace tail -f . (No es complicado; básicamente solo stat el archivo cada segundo para ver si ha cambiado. Aquí está el código fuente de la tail C ) .

EDITAR: Decepcionantemente, la tail -f popening tail -f no funciona como esperaba en Python 2.x. Parece que la iteración sobre las líneas de un archivo se implementa utilizando fread y un buffer bastante grande, incluso si se supone que el archivo no tiene buffer (como cuando subprocess.py crea el archivo, pasando bufsize = 0). Pero la tail popening sería un truco ligeramente feo de todos modos.