2015-09-23 24 views
6

Ho bisogno di leggere e scrivere file binari enormi. c'è un numero preferito o addirittura ottimale di byte (quello che chiamo BLOCK_SIZE) dovrei read() alla volta?dimensioni del blocco preferite durante la lettura/scrittura di file binari di grandi dimensioni

1 byte è certamente poco; e non penso che leggere 4GB nella RAM sia una buona idea - c'è una dimensione di blocco "migliore"? o questo dipende anche dal file system (sono su ext4)? cosa devo considerare?

python's open() fornisce anche un argomento buffering. dovrei ritoccare anche quello?

questo è il codice di esempio che solo unisce le due file in-0.data e in-1.data in out.data (nella vita reale non v'è più di elaborazione che è irrilevante per la questione a portata di mano). il BLOCK_SIZE è scelto pari a io.DEFAULT_BUFFER_SIZE che sembra essere il valore predefinito per buffering:

from pathlib import Path 
from functools import partial 

DATA_PATH = Path(__file__).parent/'../data/' 

out_path = DATA_PATH/'out.data' 
in_paths = (DATA_PATH/'in-0.data', DATA_PATH/'in-1.data') 

BLOCK_SIZE = 8192 

def process(data): 
    pass 

with out_path.open('wb') as out_file: 
    for in_path in in_paths: 
     with in_path.open('rb') as in_file: 
      for data in iter(partial(in_file.read, BLOCK_SIZE), b''): 
       process(data) 
       out_file.write(data) 
#   while True: 
#    data = in_file.read(BLOCK_SIZE) 
#    if not data: 
#     break 
#    process(data) 
#    out_file.write(data) 
+0

Non sono sicuro che esista una risposta definitiva, probabilmente dipendente dal sistema operativo, dal file system e dal disco fisico sulla macchina in questione. Se si intende essere una soluzione generica, è possibile aggiungere del codice per interrogare il sistema in modo che i parametri calcolino la risposta migliore. – cdkMoose

+0

speravo di avere 'interrogato il sistema' usando 'io.DEFAULT_BUFFER_SIZE' - ma non ho davvero esperienza con i dettagli di tutto questo ... –

+1

Non c'è una risposta statica per questo anche su un dato sistema. Dipende da un gran numero di variabili, alcune delle quali possono cambiare nel tempo o essere diverse ogni volta. e cos'altro sta facendo il tuo programma o il tuo sistema. L'approccio migliore potrebbe essere quello di scrivere qualcosa per determinare una buona dimensione in quel momento usando determinati file di test rappresentativi immutabili. In alternativa, è possibile scrivere un test standalone ed eseguirlo una volta per ottenere una stima corretta e quindi eseguire l'hardcode nell'applicazione (o effettuare la parte di test del processo di installazione o di configurazione). – martineau

risposta

4

Diamo il sistema operativo a prendere la decisione per voi. Utilizzare il modulo mmap:

https://docs.python.org/3.4/library/mmap.html

Usa meccanismo di mappatura di memoria di base del sistema operativo per la mappatura del contenuto di un file in RAM.

Si noti che esiste un limite di dimensione del file di 2 GB se si utilizza Python a 32 bit, quindi assicurarsi di utilizzare la versione a 64 bit se si decide di seguire questa rotta.

Ad esempio:

f1 = open('input_file', 'r+b') 
m1 = mmap.mmap(f1.fileno(), 0) 
f2 = open('out_file', 'a+b') # out_file must be >0 bytes on windows 
m2 = mmap.mmap(f2.fileno(), 0) 
m2.resize(len(m1)) 
m2[:] = m1 # copy input_file to out_file 
m2.flush() # flush results 

Nota che non hai mai avuto a chiamare qualsiasi read() funzioni e decidere quanti byte di portare nella RAM. Questo esempio copia solo un file in un altro, ma come hai detto nel tuo esempio, puoi fare qualsiasi elaborazione ti serva in mezzo. Si noti che mentre l'intero file è mappato su uno spazio indirizzo nella RAM, ciò non significa che sia stato effettivamente copiato lì. Verrà copiato a tratti, a discrezione del sistema operativo.

+0

se ho capito bene avrei ancora bisogno di decidere il numero di byte 'n' vorrei [' read ([n]) '] (https://docs.python.org/3.4/library/ mmap.html # mmap.mmap.read). allora sono tornato al mio problema originale. o cosa mi manca? –

+0

Ora sto provando un po 'di codice, ma in sostanza mmap ti offre un'interfaccia per i tuoi dati, oltre all'interfaccia del file. In questo modo puoi accedere, elaborare, ecc. I tuoi dati come se fossero già in un bytearray. –

+0

come posso trarre profitto da un 'bytearray'? il mio 'data' è già di tipo' '- che è perfettamente adatto a ciò di cui ho bisogno. ma sono interessato a vedere dove sta andando! –