[Python] Ottimizzare la lettura/scrittura di grossi blocchi di dati su file.

Giovanni Porcari giovanni.porcari a softwell.it
Sab 29 Giu 2013 08:45:53 CEST


Il giorno 28/giu/2013, alle ore 23:58, Gollum1 <gollum1.smeagol1 a gmail.com> ha scritto:

> attualmente uso questo codice (funzionante):
> 
>    project.source_size = 0
>    block_counter = 0
>    block = {}
> 
>    while True:
>        block[block_counter] = ib_file_data_support.Block(line_args,
> project, block_counter)
>        block[block_counter].data = fi.read(project.BUFFER_SIZE)
> 
>        # qui dovrei inserire la scrittura sul file del singolo blocco.
> 
>        if not block[block_counter].data:
>            block.pop(block_counter)
>            break
> 
>        # Aggiungo la dimensione del blocco alla dimensione del file sorgente.
>        project.source_size += len(block)
> 
>        # Eseguo tutti i processi che devo sul file del singolo blocco.
> 
>        # ELimino il blocco di dati elaborato.
>        block[block_counter].data = None
> 
>        # Incremento il contatore di blocco e leggo il prossimo blocco.
>        block_counter += 1
> 


Premesso che non ho assolutamente chiaro che cosa tu debba fare e che il mio stile di
programmazione python non è detto che sia considerato valido/standard/leggibile,
ho cercato di rifattorizzare il tuo codice come lo scriverei io.


class Block(object):
    def __init__(self,data):
        self.data=data
        
    def foo(self):
        #comando foo di blocco
        
    def bar(self):
        #comando bar di blocco
        # 
        # 

    def __len__(self):
        return len(self.data)
        
    def clear_data(self):
        self.data=None

        
class Project(object):
    def __init__(self,fi,buffer_size=1):
        self.fi=fi
        self.buffer_size=buffer_size
        
    def reset(self):
        self.source_size=0
        self.block_counter = 0
        self.blocks={}
    
    def all_blocks(self):
        data=True
        while data
            data=self.fi.read(self.buffer_size)
            yield Block(data)
        
    def run(self):
        self.reset()
        for counter,block in enumerate(self.all_blocks()):
            self.source_size+=len(block)
            self.process_block(block)
            self.store_block(block,counter)

    def process_block(self,block):
        block.foo()
        if ....:
            block.bar()
        .....
        .....
        
    def store_block(self,block,counter):
        block.clear_data()
        self.blocks[counter]=block

if __name__=='__main__':
    p=Project(fi,bufferSize=1)
    p.run()
        

In pratica ogni istanza di Block riceve i dati, li sa processare secondo diversi comandi
e li sa cancellare.

La classe Project invece viene instanziata con fi e dimensione buffer.
L'oggetto p al comando run si resetta dei contatori, prende i blocchi, li elabora e li mette nel dizionario.
Il metodo all_blocks è un generatore che si occupa di leggere i dati e restituire il Block con i dati ricevuti.

Ovviamente il tutto NON testato, scritto alla c..zo e senza nessuna pretesa che sia il modo migliore.

Ciao

G.


Maggiori informazioni sulla lista Python