2013-10-04 9 views
42

Ho uno script Python che importa un file CSV di grandi dimensioni e quindi conta il numero di occorrenze di ogni parola nel file, quindi esporta i conteggi in un altro file CSV.Cosa significa "ucciso"?

Ma quello che sta succedendo è che una volta che il conteggio parte è finito e l'esportazione inizia dice Killed nel terminale.

Non penso che questo sia un problema di memoria (se fosse stato presumo che avrei ricevuto un errore di memoria e non Killed).

Potrebbe essere che il processo richieda troppo tempo? Se è così, c'è un modo per estendere il periodo di time-out in modo da poterlo evitare?

Ecco il codice:

csv.field_size_limit(sys.maxsize) 
    counter={} 
    with open("/home/alex/Documents/version2/cooccur_list.csv",'rb') as file_name: 
     reader=csv.reader(file_name) 
     for row in reader: 
      if len(row)>1: 
       pair=row[0]+' '+row[1] 
       if pair in counter: 
        counter[pair]+=1 
       else: 
        counter[pair]=1 
    print 'finished counting' 
    writer = csv.writer(open('/home/alex/Documents/version2/dict.csv', 'wb')) 
    for key, value in counter.items(): 
     writer.writerow([key, value]) 

E il Killed accade dopo finished counting ha stampato, e il messaggio completo è:

killed (program exited with code: 137) 
+6

Messaggio il testo esatto del messaggio di errore che si stanno ottenendo. –

+2

"ucciso" generalmente indica che il processo ha ricevuto un segnale che ha causato l'uscita. In questo caso dal momento che sta accadendo allo stesso tempo dello script, c'è una buona possibilità che si tratti di una pipe rotta, il processo sta cercando di leggere o scrivere su un handle di file che è stato chiuso all'altro capo. –

+1

Non è una risposta su dove viene il messaggio 'killed', ma se è dovuto andare oltre un qualche tipo di limite di memoria di sistema, potresti essere in grado di risolverlo usando' counter.iteritems() 'invece di' counter .items() 'nel tuo ciclo finale. In Python 2, 'items' restituisce un elenco di chiavi e valori nel dizionario, che potrebbe richiedere molta memoria se è molto grande. Al contrario, 'iteritems' è un generatore che richiede solo una piccola quantità di memoria in un dato momento. – Blckknght

risposta

55

Il codice di uscita 137 (128 + 9) indica che il programma è stato chiuso a causa della ricezione del segnale 9, che è SIGKILL. Questo spiega anche il messaggio killed. La domanda è: perché hai ricevuto quel segnale?

Il motivo più probabile è probabilmente che il processo ha superato alcuni limiti nella quantità di risorse di sistema che è possibile utilizzare. A seconda del sistema operativo e della configurazione, ciò potrebbe significare che hai troppi file aperti, utilizzato troppo spazio su filesytem o qualcos'altro. Il più probabile è che il tuo programma stia usando troppa memoria. Piuttosto che rischiare cose che si interrompevano quando le allocazioni di memoria iniziarono a non funzionare, il sistema inviava un segnale di uccisione al processo che stava usando troppa memoria.

Come ho già detto in precedenza, uno dei motivi per cui si potrebbe raggiungere un limite di memoria dopo la stampa finished counting è che la chiamata a counter.items() nel ciclo finale alloca un elenco che contiene tutte le chiavi e i valori del dizionario. Se il tuo dizionario aveva molti dati, questa potrebbe essere una lista molto grande. Una possibile soluzione sarebbe quella di utilizzare counter.iteritems() che è un generatore. Anziché restituire tutti gli elementi in un elenco, ti consente di scorrere su di essi con un utilizzo di memoria molto inferiore.

Quindi, io suggerirei di provare questa, come il ciclo finale:

for key, value in counter.iteritems(): 
    writer.writerow([key, value]) 

Si noti che in Python 3, items restituisce un oggetto "Vista dizionario" che non ha la stessa testa come la versione di Python 2 del . Sostituisce iteritems, quindi se in seguito aggiorni le versioni di Python, finirai per cambiare il loop in modo che fosse.

+1

Corretto, ma anche il dizionario stesso occuperà molta memoria. OP dovrebbe prendere in considerazione la lettura e l'elaborazione del file in modo incrementale invece di tutto in una volta. – Kevin

2

dubito qualsiasi cosa sta uccidendo il processo solo perché ci vuole un a lungo. Ucciso genericamente significa che qualcosa dall'esterno ha terminato il processo, ma probabilmente non in questo caso colpendo Ctrl-C poiché ciò indurrebbe Python ad uscire da un'eccezione KeyboardInterrupt. Inoltre, in Python si otterrebbe un'eccezione MemoryError se questo fosse il problema. Quello che potrebbe accadere è che stai colpendo un bug in Python o codice di libreria standard che causa un arresto anomalo del processo.

+0

Un bug che si blocca sarebbe molto più probabile che risultasse in un segfault piuttosto che ottenere 'SIGKILL', a meno che Python non abbia un' raise (SIGKILL) 'da qualche parte nel suo codice per qualche motivo. – Kevin

14

Sono coinvolte due aree di memoria: lo stack e l'heap. Lo stack è dove viene mantenuto lo stato corrente di una chiamata di metodo (ad esempio variabili e riferimenti locali) e l'heap è il punto in cui sono memorizzati gli oggetti.recursion and memory

ho gues ci sono troppe chiavi nel counter dict che consumerà troppa memoria della regione heap, in modo che il runtime di Python solleverà un'eccezione OutOfMemory.

Per salvarlo, non creare un oggetto gigante, ad es. il contatore .

1.StackOverflow

un programma che creano troppe variabili locali.

Python 2.7.9 (default, Mar 1 2015, 12:57:24) 
[GCC 4.9.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> f = open('stack_overflow.py','w') 
>>> f.write('def foo():\n') 
>>> for x in xrange(10000000): 
... f.write('\tx%d = %d\n' % (x, x)) 
... 
>>> f.write('foo()') 
>>> f.close() 
>>> execfile('stack_overflow.py') 
Killed 

2.OutOfMemory

un programma che creats un gigante dict include troppe chiavi.

>>> f = open('out_of_memory.py','w') 
>>> f.write('def foo():\n') 
>>> f.write('\tcounter = {}\n') 
>>> for x in xrange(10000000): 
... f.write('counter[%d] = %d\n' % (x, x)) 
... 
>>> f.write('foo()\n') 
>>> f.close() 
>>> execfile('out_of_memory.py') 
Killed 

Riferimenti