Lea la línea del archivo, procésela y luego elimínela

Tengo un archivo de texto de 22 mb que contiene una lista de números (1 número por línea). Estoy tratando de que Python lea el número, procese el número y escriba el resultado en otro archivo. Todo esto funciona, pero si tengo que detener el progtwig, comienza de nuevo desde el principio. Intenté usar una base de datos mysql al principio, pero era demasiado lento. Estoy recibiendo aproximadamente 4 veces el número que se procesa de esta manera. Me gustaría poder eliminar la línea después de que se procesó el número.

with open('list.txt', 'r') as file: for line in file: filename = line.rstrip('\n') + ".txt" if os.path.isfile(filename): print "File", filename, "exists, skipping!" else: #process number and write file #(need code to delete current line here) 

Como puede ver, cada vez que se reinicia, debe buscar el nombre del archivo en el disco duro para asegurarse de que llegue al lugar donde lo dejó. Con 1.5 millones de números esto puede tomar un tiempo. Encontré un ejemplo con truncate pero no funcionó.

¿Hay comandos similares a array_shift (PHP) para python que funcionarán con archivos de texto?

Yo usaría un archivo marcador para mantener el número de la última línea procesada en lugar de volver a escribir el archivo de entrada:

 start_from = 0 try: with open('last_line.txt', 'r') as llf: start_from = int(llf.read()) except: pass with open('list.txt', 'r') as file: for i, line in enumerate(file): if i < start_from: continue filename = line.rstrip('\n') + ".txt" if os.path.isfile(filename): print "File", filename, "exists, skipping!" else: pass with open('last_line.txt', 'w') as outfile: outfile.write(str(i)) 

Este código primero verifica el archivo last_line.txt e intenta leer un número del mismo. El número es el número de línea que se procesó durante el bash anterior. Luego simplemente omite el número requerido de líneas.

Uso Redis para cosas así. Instala redis y luego pyredis y podrás tener un conjunto persistente en la memoria. Entonces puedes hacer:

 r = redis.StrictRedis('localhost') with open('list.txt', 'r') as file: for line in file: if r.sismember('done', line): continue else: #process number and write file r.sadd('done', line) 

Si no desea instalar Redis, también puede usar el módulo de archivado, asegurándose de abrirlo con la opción writeback = False. Aunque realmente recomiendo Redis, hace que cosas como esta sean mucho más fáciles.

La lectura del archivo de datos no debe ser un cuello de botella. El siguiente código lee un archivo de texto de 36 MB y 697997 líneas en aproximadamente 0,2 segundos en mi máquina:

 import time start = time.clock() with open('procmail.log', 'r') as f: lines = f.readlines() end = time.clock() print 'Readlines time:', end-start 

Porque produjo el siguiente resultado:

 Readlines time: 0.1953125 

Tenga en cuenta que este código produce una lista de líneas de una sola vez.

Para saber dónde ha estado, simplemente escriba la cantidad de líneas que ha procesado en un archivo. Luego, si quieres intentarlo de nuevo, lee todas las líneas y omite las que ya has hecho:

 import os # Raad the data file with open('list.txt', 'r') as f: lines = f.readlines() skip = 0 try: # Did we try earlier? if so, skip what has already been processed with open('lineno.txt', 'r') as lf: skip = int(lf.read()) # this should only be one number. del lines[:skip] # Remove already processed lines from the list. except: pass with open('lineno.txt', 'w+') as lf: for n, line in enumerate(lines): # Do your processing here. lf.seek(0) # go to beginning of lf lf.write(str(n+skip)+'\n') # write the line number lf.flush() os.fsync() # flush and fsync make sure the lf file is written.