149 votes

Que signifie 'killed' lors du traitement d'un énorme fichier CSV avec Python, qui s'arrête soudainement?

J'ai un script Python qui importe un grand fichier CSV, puis compte le nombre d'occurrences de chaque mot dans le fichier, puis exporte les comptes dans un autre fichier CSV.

Mais ce qui se passe, c'est qu'une fois que la partie du comptage est terminée et que l'exportation commence, il affiche Killed dans le terminal.

Je ne pense pas que ce soit un problème de mémoire (si c'était le cas, je suppose que j'obtiendrais une erreur de mémoire et pas Killed).

Est-ce que le processus prendrait trop de temps ? Si oui, y a-t-il un moyen de prolonger la période de time-out pour éviter cela ?

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

Et le Killed se produit après que finished counting a été imprimé, et le message complet est :

killed (program exited with code: 137)

143voto

Blckknght Points 20780

Le code de sortie 137 (128+9) indique que votre programme s'est terminé en raison de la réception du signal 9, qui est SIGKILL. Cela explique également le message killed. La question est, pourquoi avez-vous reçu ce signal?

La raison la plus probable est probablement que votre processus a dépassé une limite dans la quantité de ressources système que vous êtes autorisé à utiliser. Selon votre système d'exploitation et la configuration, cela pourrait signifier que vous aviez trop de fichiers ouverts, utilisé trop d'espace disque ou autre chose. La raison la plus probable est que votre programme utilisait trop de mémoire. Plutôt que de risquer des interruptions lorsque les allocations de mémoire commençaient à échouer, le système a envoyé un signal d'arrêt au processus qui utilisait trop de mémoire.

Comme je l'ai commenté précédemment, une raison pour laquelle vous pourriez atteindre une limite de mémoire après avoir imprimé finished counting est que votre appel à counter.items() dans votre dernière boucle alloue une liste qui contient toutes les clés et valeurs de votre dictionnaire. Si votre dictionnaire contenait beaucoup de données, cela pourrait être une liste très volumineuse. Une solution possible serait d'utiliser counter.iteritems() qui est un générateur. Plutôt que de renvoyer tous les éléments dans une liste, il vous permet d'itérer sur eux avec beaucoup moins d'utilisation de mémoire.

Je vous suggère donc d'essayer ceci, comme votre dernière boucle :

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

Remarquez qu'en Python 3, items renvoie un objet "vue de dictionnaire" qui n'a pas le même surcoût que la version Python 2. Il remplace iteritems, donc si vous mettez à jour les versions de Python plus tard, vous devrez revenir à la boucle telle qu'elle était.

35voto

ROY Points 894

Il y a deux zones de stockage impliquées : la pile et le tas. La pile est l'endroit où l'état actuel d'un appel de méthode est conservé (c'est-à-dire les variables locales et les références), et le tas est l'endroit où les objets sont stockés. récursion et mémoire

Je suppose qu'il y a trop de clés dans le counter dict qui vont consommer trop de mémoire de la région du tas, donc l'exécution de Python va lever une exception OutOfMemory.

Pour l'éviter, ne créez pas un objet géant, par exemple le counter.

1.StackOverflow

un programme qui crée trop de variables locales.

Python 2.7.9 (par défaut, 1er mars 2015, 12:57:24) 
[GCC 4.9.2] sur linux2
Tapez "help", "copyright", "credits" ou "license" pour plus d'informations.
>>> 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 programme qui crée un dict géant incluant trop de clés.

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

Références

7voto

ivanleoncz Points 1940

Le plus probable, c'est que vous avez manqué de mémoire, donc le Kernel a tué votre processus.

Avez-vous entendu parler de OOM Killer?

Voici un journal d'un script que j'ai développé pour traiter un énorme ensemble de données à partir de fichiers CSV :

Mar 12 18:20:38 server.com kernel: [63802.396693] En rupture de stock de mémoire : Processus 12216 (python3) tué score 915 ou sacrifice d'enfant
Mar 12 18:20:38 server.com kernel: [63802.402542] Processus 12216 (python3) tué total-vm :9695784ko, anon-rss :7623168ko, file-rss :4ko, shmem-rss :0ko
Mar 12 18:20:38 server.com kernel: [63803.002121] oom_reaper : processus 12216 (python3) moissonné, maintenant anon-rss :0ko, file-rss :0ko, shmem-rss :0ko

Cela vient de /var/log/syslog.

En gros :

PID 12216 élu comme victime (en raison de son utilisation de +9Go de total-vm), alors oom_killer l'a moissonné.

Voici un article sur le comportement OOM.

5voto

Wingware Points 490

Je doute que quelque chose tue le processus juste parce que cela prend beaucoup de temps. Être tué signifie généralement que quelque chose de l'extérieur a terminé le processus, mais probablement pas dans ce cas en appuyant sur Ctrl-C car cela entraînerait la sortie de Python sur une exception KeyboardInterrupt. De plus, en Python, vous obtiendriez une exception MemoryError si c'était le problème. Ce qui pourrait se passer, c'est que vous rencontrez un bogue dans le code Python ou de bibliothèque standard qui provoque un crash du processus.

4voto

JavaScriptDude Points 140

Je viens de vivre la même chose lorsque j'ai essayé d'exécuter un script Python à partir d'un dossier partagé dans VirtualBox dans le nouveau Ubuntu 20.04 LTS. Python s'est arrêté avec Killed pendant le chargement de ma propre bibliothèque personnelle. Lorsque j'ai déplacé le dossier vers un répertoire local, le problème a disparu. Il semble que l'arrêt Killed s'est produit lors des importations initiales de ma bibliothèque car j'ai eu des messages indiquant des bibliothèques manquantes une fois le dossier déplacé.

Le problème a disparu après avoir redémarré mon ordinateur.

Par conséquent, les utilisateurs peuvent essayer de déplacer le programme dans un répertoire local s'il est sur un partage de quelque nature que ce soit, ou cela pourrait être un problème transitoire nécessitant simplement un redémarrage du système d'exploitation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X