Was bedeutet "getötet", wenn eine Verarbeitung einer riesigen CSV mit Python plötzlich stoppt?

87

Ich habe ein Python-Skript, das eine große CSV-Datei importiert und dann die Anzahl der Vorkommen jedes Wortes in der Datei zählt und dann die Anzahl in eine andere CSV-Datei exportiert.

Aber was passiert ist, dass, sobald dieser Zählteil fertig ist und der Export beginnt, es heißt Killed im Terminal steht.

Ich denke nicht, dass dies ein Speicherproblem ist (wenn es so wäre, würde ich wahrscheinlich einen Speicherfehler bekommen und nicht Killed ).

Könnte es sein, dass der Prozess zu lange dauert? Wenn ja, gibt es eine Möglichkeit, die Auszeit zu verlängern, damit ich dies vermeiden kann?

Hier ist der Code:

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])

Und das Killedpassiert, nachdem finished countinggedruckt wurde, und die vollständige Nachricht lautet:

killed (program exited with code: 137)
user1893354
quelle
6
Veröffentlichen Sie den genauen Wortlaut der Fehlermeldung, die Sie erhalten.
Robert Harvey
2
"getötet" bedeutet im Allgemeinen, dass der Prozess ein Signal empfangen hat, das zum Beenden des Prozesses geführt hat. In diesem Fall besteht eine gute Chance, dass der Prozess aus einem am anderen Ende geschlossenen Dateihandle liest oder in dieses schreibt, da es zur gleichen Zeit wie das Skript ausgeführt wird.
Andrew Clark
3
Es ist keine Antwort darauf, woher die killedNachricht kommt, aber wenn es darum geht, eine Art Systemspeicherlimit zu überschreiten, können Sie dies möglicherweise beheben, indem Sie counter.iteritems()statt counter.items()in Ihrer letzten Schleife verwenden. Gibt in Python 2 itemseine Liste der Schlüssel und Werte im Wörterbuch zurück, die bei sehr großem Speicher möglicherweise viel Speicher benötigen. Im Gegensatz dazu iteritemsist ein Generator, der zu einem bestimmten Zeitpunkt nur wenig Speicher benötigt.
Blckknght

Antworten:

98

Der Exit-Code 137 (128 + 9) zeigt an, dass Ihr Programm aufgrund des Empfangssignals 9 beendet wurde SIGKILL. Dies erklärt auch die killedNachricht. Die Frage ist, warum haben Sie dieses Signal erhalten?

Der wahrscheinlichste Grund ist wahrscheinlich, dass Ihr Prozess eine bestimmte Anzahl von Systemressourcen überschritten hat, die Sie verwenden dürfen. Abhängig von Ihrem Betriebssystem und Ihrer Konfiguration kann dies bedeuten, dass Sie zu viele geöffnete Dateien, zu viel Dateisystemspeicherplatz oder etwas anderes verwendet haben. Am wahrscheinlichsten ist, dass Ihr Programm zu viel Speicher belegt hat. Anstatt zu riskieren, dass Dinge kaputt gehen, wenn die Speicherzuweisungen fehlschlagen, hat das System ein Kill-Signal an den Prozess gesendet, der zu viel Speicher verwendet.

Wie ich bereits erwähnt habe, besteht ein Grund dafür, dass Sie nach dem Drucken möglicherweise an ein Speicherlimit stoßen, finished countingdarin, dass Ihr Aufruf counter.items()in Ihrer letzten Schleife eine Liste zuweist, die alle Schlüssel und Werte aus Ihrem Wörterbuch enthält. Wenn Ihr Wörterbuch viele Daten enthält, ist dies möglicherweise eine sehr große Liste. Eine mögliche Lösung wäre die Verwendung counter.iteritems()eines Generators. Anstatt alle Elemente in einer Liste zurückzugeben, können Sie sie mit viel weniger Speicherbedarf durchlaufen.

Daher würde ich vorschlagen, dies als letzte Schleife zu versuchen:

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

Beachten Sie, dass in Python 3 itemsein Objekt "Dictionary View" zurückgegeben wird, das nicht den gleichen Overhead wie die Version von Python 2 hat. Es wird ersetzt iteritems. Wenn Sie also später Python-Versionen aktualisieren, ändern Sie die Schleife wieder in den ursprünglichen Zustand.

Blckknght
quelle
2
Richtig, aber das Wörterbuch selbst beansprucht auch viel Speicher. OP sollte in Betracht ziehen, die Datei schrittweise und nicht alle gleichzeitig zu lesen und zu verarbeiten.
Kevin
24

Es gibt zwei Speicherbereiche: den Stapel und den Heap. Auf dem Stapel wird der aktuelle Status eines Methodenaufrufs gespeichert (dh lokale Variablen und Referenzen), und auf dem Heap werden Objekte gespeichert. Rekursion und Erinnerung

Ich vermute, es gibt zu viele Schlüssel im counterDiktat, die zu viel Speicher der Heap-Region verbrauchen, sodass die Python-Laufzeit ein OutOfMemory auslöst Ausnahme .

Erstellen Sie zum Speichern kein riesiges Objekt, z . B. den Zähler .

1.StackOverflow

Ein Programm, das zu viele lokale Variablen erstellt.

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

Ein Programm, das einen Riesen erschafft, dictenthält zu viele Schlüssel.

>>> 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

Verweise
ROY
quelle
2

Ich bezweifle, dass irgendetwas den Prozess beendet, nur weil es lange dauert. Generisch getötet bedeutet, dass etwas von außen den Prozess beendet hat, aber in diesem Fall wahrscheinlich nicht, wenn Strg-C gedrückt wird, da dies dazu führen würde, dass Python bei einer KeyboardInterrupt-Ausnahme beendet wird. Außerdem würden Sie in Python eine MemoryError-Ausnahme erhalten, wenn dies das Problem wäre. Was möglicherweise passiert, ist, dass Sie auf einen Fehler in Python oder Standardbibliothekscode stoßen, der einen Absturz des Prozesses verursacht.

Wingware
quelle
Ein Absturzfehler führt viel eher zu einem Segfault als zu einem Fehler SIGKILL, es sei denn, Python hat raise(SIGKILL)aus irgendeinem Grund irgendwo in seinem Code einen Fehler .
Kevin
1
Ein Fehler in Python würde SIGKILL nicht senden.
qwr
2

Höchstwahrscheinlich ist Ihnen der Speicher ausgegangen, sodass der Kernel Ihren Prozess abgebrochen hat.

Hast du von OOM Killer gehört ?

Hier ist ein Protokoll eines Skripts, das ich für die Verarbeitung eines großen Datensatzes aus CSV-Dateien entwickelt habe:

Mar 12 18:20:38 server.com kernel: [63802.396693] Out of memory: Kill process 12216 (python3) score 915 or sacrifice child
Mar 12 18:20:38 server.com kernel: [63802.402542] Killed process 12216 (python3) total-vm:9695784kB, anon-rss:7623168kB, file-rss:4kB, shmem-rss:0kB
Mar 12 18:20:38 server.com kernel: [63803.002121] oom_reaper: reaped process 12216 (python3), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

Es wurde aus genommen /var/log/syslog.

Grundsätzlich:

PID 12216 wurde als Opfer gewählt (aufgrund der Verwendung von + 9 GB total-vm), also erntete oom_killer es.

Hier ist ein Artikel über das OOM-Verhalten .

ivanleoncz
quelle
1
+1, nur um zu verdeutlichen, um zu verstehen, wie viel RAM mein Programm zu verwenden versucht, sollte ich die Werte total-vm, anon-rss, file-rss addieren? Außerdem gibt total-vm an, wie viel mein Programm verwendet und nicht den tatsächlich verfügbaren Speicher, oder? Entschuldigung, begrenzte Kenntnisse.
Momo
1
Mein Wissen ist auch in diesem Zusammenhang begrenzt, @momo. Ich habe etwas Zeit für weitere Untersuchungen, aber ich habe diesen Beitrag gefunden, der helfen könnte: stackoverflow.com/questions/18845857/… . Was ich Ihnen sagen kann, ist, dass total-vm tatsächlich die Menge an Speicher ist, die von dem Prozess verwendet wird.
ivanleoncz
0

Ich hatte gerade das gleiche Problem, als ich versuchte, ein Python-Skript aus einem freigegebenen Ordner in VirtualBoxder neuen Ubuntu 20.04 LTS auszuführen . Python wurde Killedbeim Laden meiner persönlichen Bibliothek gerettet . Als ich den Ordner in ein lokales Verzeichnis verschoben habe, ist das Problem behoben. Es scheint, dass dieKilled Stopp während der ersten Importe meiner Bibliothek aufgetreten ist, da ich Nachrichten über fehlende Bibliotheken erhalten habe, nachdem ich den Ordner verschoben habe.

Das Problem wurde behoben, nachdem ich meinen Computer neu gestartet hatte.

Daher möchten Benutzer möglicherweise versuchen, das Programm in ein lokales Verzeichnis zu verschieben, wenn es sich um eine Freigabe handelt, oder wenn es sich um ein vorübergehendes Problem handelt, das nur einen Neustart des Betriebssystems erfordert.

Timothy C. Quinn
quelle