2013-06-12 9 views
7

Mi piacerebbe capire la differenza nell'utilizzo della RAM di questi metodi durante la lettura di un file di grandi dimensioni in python.Leggi file in blocchi - Utilizzo RAM, leggi Stringhe da file binari

versione 1, che si trova qui su StackOverflow:

def read_in_chunks(file_object, chunk_size=1024): 
    while True: 
     data = file_object.read(chunk_size) 
     if not data: 
      break 
     yield data 


f = open(file, 'rb') 
for piece in read_in_chunks(f): 
    process_data(piece)   
f.close() 

versione 2, ho usato questo prima ho trovato il codice di cui sopra:

f = open(file, 'rb') 
while True: 
    piece = f.read(1024)  
    process_data(piece)   
f.close() 

Il file viene letto in parte in entrambe le versioni. E il pezzo attuale potrebbe essere elaborato. Nel secondo esempio, piece sta ottenendo nuovi contenuti in ogni ciclo, quindi ho pensato che questo avrebbe fatto il lavoro a non caricare il file completo in memoria ..?

Ma non capisco cosa faccia esattamente lo yield, e sono abbastanza sicuro di aver sbagliato qualcosa qui. Qualcuno potrebbe spiegarmelo?


C'è un'altra cosa che mi lascia perplesso, oltre il metodo utilizzato:

Il contenuto del pezzo ho letto è definito dal chunk-size, 1 KB negli esempi precedenti. Ma ... cosa succede se ho bisogno di cercare le stringhe nel file? Qualcosa come "ThisIsTheStringILikeToFind"?

A seconda di dove nel file si verifica la stringa, potrebbe essere che un pezzo contiene la parte "ThisIsTheStr" - e il pezzo successivo conterrà "ingILikeToFind". Utilizzando tale metodo non è possibile rilevare l'intera stringa in alcun pezzo.

C'è un modo per leggere un file in blocchi, ma in qualche modo interessa tali stringhe?

Qualsiasi aiuto o idea è benvenuto,

saluta!

+0

si potrebbe scrivere il primo frammento come 'per pezzo a iter (parziale (f.read, chunk_size), b "") : process_data (chunk) '(presuppone la modalità binaria). La risposta all'ultima domanda è sì: basta verificare se il blocco termina con uno qualsiasi dei prefissi della stringa e il blocco successivo inizia con il suffisso corrispondente. – jfs

+0

Grazie per aver menzionato "iter" - non lo sapevo! Circa la seconda domanda: vuoi dire che potrei controllare se il pezzo termina con 'T' o' Th' o 'Thi' o' This' - e così via? Hmm, bella idea! Grazie! – xph

risposta

15

yield è la parola chiave in python utilizzata per le espressioni del generatore. Ciò significa che la prossima volta che la funzione viene chiamata (o iterata su), l'esecuzione verrà riavviata nel punto esatto in cui è stata interrotta l'ultima volta che l'hai chiamata. Le due funzioni funzionano in modo identico; l'unica differenza è che il primo usa un pochino di spazio in più per le chiamate rispetto al secondo. Tuttavia, il primo è molto più riutilizzabile, quindi dal punto di vista del design del programma, il primo è in realtà migliore.

EDIT: Inoltre, un'altra differenza è che il primo sarà smettere di leggere una volta tutti i dati sono stati letti, come dovrebbe, ma il secondo sarà solo smettere una volta sia f.read() o process_data() genera un'eccezione. Al fine di avere il secondo lavoro correttamente, è necessario modificare in questo modo:

f = open(file, 'rb') 
while True: 
    piece = f.read(1024) 
    if not piece: 
     break 
    process_data(piece) 
f.close() 
+0

Grazie per la tua risposta! Capisco che la prima versione sia meglio riusabile, definisce una funzione che potrebbe essere utile anche in altri progetti. Da questo deriva lo "stack stack" più grande, immagino? Creare una funzione?Ma non c'è differenza nell'utilizzo della RAM del file stesso? Ho trovato qualche documentazione sulle funzioni del generatore, non è così facile da capire quando si hanno sempre in mente funzioni comuni - ma se ho capito bene, la prima versione sarebbe 'return' solo il primo pezzo del file e il ciclo 'for' passerebbe in rassegna i dati di' piece', senza 'yield'? – xph

+0

Se ti è piaciuta la mia risposta, potresti contrassegnarla come risposta accettata? (In realtà ottieni 2 rappresentanti per farlo) – AJMansfield

+0

Oh, sì! Certo, scusa ... :-) – xph