2016-03-15 16 views
6

Ho grandi file compressi gzip. Ho scritto un pezzo di codice per dividere quei file in quelli più piccoli. Posso specificare il numero di righe per file. Il fatto è che recentemente ho aumentato il numero di linee per divisione da a 16.000.000 e quando elaboro file più grandi, la divisione non avverrà. A volte viene prodotto con successo un file più piccolo, , a volte uno viene prodotto ma pesa solo 40B o 50B, il che è un errore . Ho cercato di cogliere un'eccezione per questo osservando quelli generati nel codice . Quindi il mio codice è simile al seguente:gzip non riesce a scrivere una grande quantità di dati nel file

def writeGzipFile(file_name, content): 
    import gzip 
    with gzip.open(file_name, 'wb') as f: 
     if not content == '': 
      try: 
       f.write(content) 
      except IOError as ioe: 
       print "I/O ERROR wb", ioe.message 
      except ValueError as ve: 
       print "VALUE ERROR wb: ", ve.message 
      except EOFError as eofe: 
       print "EOF ERROR wb: ", eofe.message 
      except: 
       print "UNEXPECTED ERROR wb" 

Il fatto è che quando il contenuto è troppo alto, in relazione al numero di linee, spesso ricevo il messaggio "errore imprevisto". Quindi non ho idea di quale tipo di errore venga generato qui.

Alla fine ho scoperto che il numero di linee era il problema, e sembra che lo gzip di Python non riesca a scrivere una tale quantità di dati in un file in una volta. Abbassare il numero di righe per divisione in basso a 4.000.000 di opere. Tuttavia vorrei dividere il contenuto e scrivere sequenzialmente su un file per assicurarmi che anche il contenuto di dati elevato venga scritto.

Quindi mi piacerebbe sapere come trovare il numero massimo di caratteri che possono essere scritti di sicuro in una volta in un file utilizzando gzip, senza alcun errore.


EDIT 1

Così ho caugth tutte le eccezioni rimanenti (non sapevo che fosse possibile raggiungere semplicemente Exception sorry):

def writeGzipFile(file_name, content, file_permission=None): 
    import gzip, traceback 
    with gzip.open(file_name, 'wb') as f: 
     if not content == '': 
      try: 
       f.write(content) 
      except IOError as ioe: 
       print "I/O ERROR wb", ioe.message 
      except ValueError as ve: 
       print "VALUE ERROR wb: ", ve.message 
      except EOFError as eofe: 
       print "EOF ERROR wb: ", eofe.message 
      except Exception, err: 
       print "EXCEPTION:", err.message 
       print "TRACEBACK_1:", traceback.print_exc(file=sys.stdout) 
      except: 
       print "UNEXPECTED ERROR wb" 

L'errore è di circa int dimensioni. Non ho mai pensato che avrei superato la dimensione int un giorno:

EXCEPTION: size does not fit in an int 
TRACEBACK_1:Traceback (most recent call last): 
    File "/home/anadin/dev/illumina-project-restructor_mass-splitting/illumina-project-restructor/tools/file_utils/file_compression.py", line 131, in writeGzipFile 
    f.write(content) 
    File "/usr/local/cluster/python2.7/lib/python2.7/gzip.py", line 230, in write 
    self.crc = zlib.crc32(data, self.crc) & 0xffffffffL 
OverflowError: size does not fit in an int 
None 

Ok, quindi la dimensione massima di un int essere 2,147,483,647, il mio blocco di dati è di circa 3.854.674,09 mila secondo il mio registro. Questo blocco è una stringa a cui ho applicato la funzione __len__().

Così come avevo programmato di fare, e come suggeriva Antti Haapala, sto per leggere pezzi più piccoli alla volta in modo da scriverli in sequenza su file più piccoli.

+1

Rispondere dopo aver risolto il problema - * non utilizzare blocchi di eccezioni senza nome * - perché causano proprio questo tipo di problema nascondendo il meccanismo di errore. (A meno che tu * davvero * non ti interessi se un'operazione fallisce). – SiHa

+1

Se funziona quando si riduce la quantità di dati che si sta elaborando, quindi sono abbastanza sicuro che il problema è che si tratti di * tutti * i dati in una singola stringa: 'contenuto'. Questo probabilmente consumerà tutta la tua memoria. Non vedo il resto del tuo codice, ma in generale vuoi leggere una piccola porzione di dati (di solito una linea), fare tutto ciò che vuoi e poi dargli da mangiare a gzip che poi scriverà quel piccolo pezzo su disco .Quindi ripeti questi 16 milioni (o comunque spesso) volte, e in nessun caso la memoria occupata sarà più di una singola riga ... – Carpetsmoker

+0

FWIW, [questa risposta] (http://stackoverflow.com/a/27037303/ 4014959) Ho scritto un paio di anni fa mostra come gzip un file blocco per blocco. –

risposta

5

In ogni caso, sospetto che il motivo sia una sorta di errore di memoria insufficiente. Non è abbastanza chiaro per me perché non hai scritto questi dati in quantità minore una volta; qui utilizzando il metodo di chunksfrom this answer:

def chunks(l, n): 
    """Yield successive n-sized chunks from l.""" 
    for i in xrange(0, len(l), n): 
     yield l[i:i+n] 

... 
with gzip.open(file_name, 'wb') as f: 
    for chunk in chunks(content, 65536): 
     f.write(chunk) 

Cioè, lo fai come ci si mangia un elefante, prendere un boccone alla volta.

+0

Grazie, il mio problema è un po 'più complesso, ma il principio è quello di scrivere davvero blocchi più piccoli alla volta. A proposito, perché stai limitando il chunk a 65536? Qui sono limitato dalla dimensione int come appare. Posso sostituire la tua taglia con la gamma int? O qualcosa di più efficiente, qual è la tua opinione? – kaligne

+0

Ancora non tenterei la fortuna! Avresti esaurito la memoria prima. Questo splicing effettivamente * copia * quella parte di una stringa. –

+0

@kaligne: 64k è una buona dimensione del blocco. Potresti ottenere prestazioni leggermente più veloci con una dimensione di blocco maggiore, a seconda dell'hardware, ma IME il miglioramento è molto marginale e ho condotto test su una gamma di unità, sia meccaniche che allo stato solido. Ricorda che ** non ** si interfaccia direttamente con l'hardware, stai passando attraverso il software del driver del sistema operativo che utilizza un buffering del disco efficiente e le unità hanno anche le loro cache incorporate. –

Problemi correlati