2012-07-05 12 views
15

Tengo unos 50 GB de archivo de texto y estoy comprobando los primeros caracteres de cada línea y escribiéndolos en otros archivos especificados para ese texto inicial.Archivo de Python abrir/cerrar cada vez vs mantenerlo abierto hasta que finalice el proceso

Por ejemplo. mi entrada contiene:

cow_ilovecow 
dog_whreismydog 
cat_thatcatshouldgotoreddit 
dog_gotitfromshelter 
............... 

Por lo tanto, quiero procesarlos de vaca, perro y gato (unos 200) Categorías de así,

if writeflag==1: 
    writefile1=open(writefile,"a") #writefile is somedir/dog.txt.... 
    writefile1.write(remline+"\n") 
    #writefile1.close() 

es así, ¿cuál es la mejor manera, debo ¿cerca? De lo contrario, si lo mantengo abierto, ¿está writefile1=open(writefile,"a") haciendo lo correcto?

Respuesta

28

Definitivamente usted debería tratar de abrir/cerrar el archivo lo menos posible

Porque incluso comparando con leer el archivo/escritura, abrir/cerrar archivos es mucho más caro

Considérese dos bloques de código:

f=open('test1.txt', 'w') 
for i in range(1000): 
    f.write('\n') 
f.close() 

y

for i in range(1000): 
    f=open('test2.txt', 'a') 
    f.write('\n') 
    f.close() 

La primera se toma 0.025s mientras que el segundo toma 0.309s

+0

Genial, debería haber probado, ahora esto tiene mucho más sentido hacer muy pocas declaraciones abiertas/cerradas – Ananta

1

¡Manténgalo abierto todo el tiempo! De lo contrario, le dice al sistema que ha terminado de escribir todo el tiempo y que podría decidir enjuagarlo en el disco en lugar de almacenarlo en el búfer. Y por razones obvias n las escrituras en disco son mucho más costosas que escritura en disco.

Si desea agregar al archivo y no sobrescribirlo, entonces sí, a es el modo correcto.

+0

Gracias, yo siempre aunque al abrir el archivo se carga todo el archivo en la memoria. – Ananta

4

Utilice la instrucción with, se cierra automáticamente los archivos para usted, hacer todas las operaciones dentro del bloque with, por lo que va a mantener los archivos abiertos para usted y cerrará los archivos una vez que estás fuera del bloque with .

with open(inputfile)as f1, open('dog.txt','a') as f2,open('cat.txt') as f3: 
    #do something here 

EDIT: Si conoces a todos los posibles nombres de archivo que se utilizará antes de la compilación de su código a continuación, utilizando with es una opción mejor y si no lo hace, entonces debería usar su enfoque, pero en lugar de cerrando el archivo puede flush los datos al archivo usando writefile1.flush()

+0

La declaración 'with' puede ser un poco torpe si está abriendo un nuevo archivo para cada prefijo en la entrada, y no está claro si todos los prefijos posibles se conocen en tiempo de compilación. – geoffspear

+0

@Wooble ¡buen punto! usar 'con' significa que necesita saber todos los nombres de archivo antes del tiempo de ejecución, pero si conoce todos los nombres de los archivos, en ese caso 'con' es una mejor opción. –

+1

Además, con 200 categorías, una dict de archivos en lugar de 200 variables es probablemente la mejor solución. – geoffspear

-1

Las operaciones IO consumen demasiado tiempo. Abre y cierra el archivo, también.

Es mucho más rápido si abre ambos archivos (la entrada y la salida), utiliza un búfer de memoria con, digamos, 10MB de tamaño para su procesamiento de texto y luego lo escribe en el archivo de salida. Por ejemplo:

file = {} # just initializing dicts 
filename = {} 
with open(file) as f: 
    file['dog'] = None 
    buffer = '' 
    ... 
    #maybe there is a loop here 
    if writeflag: 
     if file['dog'] == None: 
      file['dog'] = open(filename['dog'], 'a') 
     buffer += remline + '\n' 
    if len(buffer) > 1024*1000*10: # 10MB of text 
     files['dog'].write(buffer) 
     buffer = '' 

for v in files.values(): 
    v.close() 
+0

Podría ir por este camino, pero supongo que debería ser un búfer diferente para cada prefijo, por lo que escribir en todos los archivos después de procesar ciertas líneas en los archivos originales puede ser una mejor opción ¿no? – Ananta

+0

-1, eso no es nada que deba hacer en el código de su aplicación. Los sistemas operativos son lo suficientemente inteligentes como para amortiguar las operaciones de lectura/escritura por sí solos si los permite (es decir, no cierra/vuelve a abrir el archivo después de cada operación). Sin mencionar que usar una cadena para el buffer es bastante caro en comparación con una lista. – ThiefMaster

+0

@ThiefMaster Acabo de hacer un punto de referencia simple y resultó que usar un búfer con cadena era un 13% más rápido que usar io directamente, y un 5% más rápido que usar un búfer con la lista. De hecho, las operaciones de cadena en Python están realmente optimizadas. Puede verificar el código aquí: http://paste.kde.org/513206/ –

Cuestiones relacionadas