¿Qué significa ‘matado’ cuando se procesa un CSV enorme con Python, que se detiene repentinamente?

8 minutos de lectura

avatar de usuario
usuario1893354

Tengo un script de Python que importa un archivo CSV grande y luego cuenta la cantidad de ocurrencias de cada palabra en el archivo, luego exporta los conteos a otro archivo CSV.

Pero lo que pasa es que una vez terminada esa parte de conteo y comienza la exportación dice Killed en la terminal

No creo que sea un problema de memoria (si lo fuera, supongo que obtendría un error de memoria y no Killed).

¿Puede ser que el proceso esté tardando demasiado? Si es así, ¿hay alguna manera de extender el período de tiempo de espera para poder evitar esto?

Aquí está el código:

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

Y el Killed sucede después finished counting ha impreso, y el mensaje completo es:

killed (program exited with code: 137)

  • Publique las palabras exactas del mensaje de error que está recibiendo.

    – Roberto Harvey

    4 oct 2013 a las 19:46


  • “matado” generalmente significa que el proceso recibió alguna señal que provocó su salida. En este caso, dado que ocurre al mismo tiempo que el script, es muy probable que se trate de una tubería rota, el proceso está tratando de leer o escribir en un identificador de archivo que se cerró en el otro extremo.

    – Andrés Clark

    04/10/2013 a las 19:47

  • No es una respuesta acerca de dónde está el killed de donde proviene el mensaje, pero si se debe a algún tipo de límite de memoria del sistema, es posible que pueda solucionarlo utilizando counter.iteritems() en vez de counter.items() en tu bucle final. En Python 2, items devuelve una lista de las claves y valores del diccionario, que puede requerir mucha memoria si es muy grande. A diferencia de, iteritems es un generador que solo requiere una pequeña cantidad de memoria en un momento dado.

    – Caballero negro

    04/10/2013 a las 22:37

El código de salida 137 (128+9) indica que su programa salió debido a la recepción de la señal 9, que es SIGKILL. Esto también explica la killed mensaje. La pregunta es, ¿por qué recibiste esa señal?

La razón más probable es que su proceso cruzó algún límite en la cantidad de recursos del sistema que puede usar. Dependiendo de su sistema operativo y configuración, esto podría significar que tenía demasiados archivos abiertos, usó demasiado espacio en el sistema de archivos o algo más. Lo más probable es que su programa estuviera usando demasiada memoria. En lugar de arriesgarse a que se rompieran las cosas cuando las asignaciones de memoria comenzaban a fallar, el sistema envió una señal de interrupción al proceso que estaba usando demasiada memoria.

Como comenté anteriormente, una de las razones por las que podría alcanzar un límite de memoria después de imprimir finished counting es esa tu llamada a counter.items() en su bucle final asigna una lista que contiene todas las claves y valores de su diccionario. Si su diccionario tuviera muchos datos, esta podría ser una lista muy grande. Una posible solución sería usar counter.iteritems() que es un generador. En lugar de devolver todos los elementos de una lista, le permite iterarlos con mucho menos uso de memoria.

Entonces, sugiero probar esto, como su ciclo final:

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

Tenga en cuenta que en Python 3, items devuelve un objeto de “vista de diccionario” que no tiene la misma sobrecarga que la versión de Python 2. reemplaza iteritemspor lo que si luego actualiza las versiones de Python, terminará cambiando el bucle de nuevo a la forma en que estaba.

  • Correcto, pero el propio diccionario también ocupará mucha memoria. OP debería considerar leer y procesar el archivo de forma incremental en lugar de todo a la vez.

    –Kevin

    4 de abril de 2016 a las 4:04

avatar de usuario
roy

Hay dos áreas de almacenamiento involucradas: la pila y el montón. La pila es donde se guarda el estado actual de una llamada a método (es decir, variables locales y referencias), y el montón es donde se almacenan los objetos. recursividad y memoria

Supongo que hay demasiadas llaves en el counter dicta que consumirá demasiada memoria de la región del montón, por lo que el tiempo de ejecución de Python generará un Sin memoria excepción.

Para guardarlo, no cree un objeto gigante, por ejemplo, el encimera.

1. Desbordamiento de pila

un programa que crea demasiadas variables locales.

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.Memoria insuficiente

un programa que crea un gigante dict incluye demasiadas llaves.

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

Referencias

avatar de usuario
ivanleoncz

Lo más probable es que se haya quedado sin memoria, por lo que el Kernel eliminó su proceso.

¿Has oído hablar de Asesino OOM?

Aquí hay un registro de un script que desarrollé para procesar un gran conjunto de datos de archivos CSV:

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

fue tomado de /var/log/syslog.

Básicamente:

PID 12216 elegido como víctima (debido a su uso de +9Gb de total-vm), por lo que oom_asesino lo coseché.

Aquí hay un artículo sobre Comportamiento OOM.

  • +1, solo para aclarar, para comprender cuánta RAM está tratando de usar mi programa, ¿debo sumar los valores total-vm, anon-rss, file-rss? Además, total-vm da cuánto está usando mi programa y no la memoria disponible real, ¿verdad? Lo siento, conocimientos limitados.

    – momo

    28 de julio de 2020 a las 3:48

  • Mi conocimiento también es limitado en este contexto, @momo. No tengo tiempo para más investigaciones, pero encontré esta publicación que podría ayudar: stackoverflow.com/questions/18845857/… . Lo que puedo decirles es que, de hecho, total-vm, es la cantidad de memoria utilizada por el proceso.

    – ivanleoncz

    28 de julio de 2020 a las 18:07

Dudo que algo esté matando el proceso solo porque lleva mucho tiempo. Killed genéricamente significa que algo del exterior terminó el proceso, pero probablemente no en este caso presionando Ctrl-C ya que eso haría que Python saliera con una excepción KeyboardInterrupt. Además, en Python obtendría la excepción MemoryError si ese fuera el problema. Lo que podría estar sucediendo es que está experimentando un error en Python o en el código de la biblioteca estándar que provoca un bloqueo del proceso.

Me acaba de pasar lo mismo cuando traté de ejecutar un script de python desde una carpeta compartida en VirtualBox dentro del nuevo Ubuntu 20.04 LTS. Python rescatado con Killed mientras cargaba mi propia biblioteca personal. Cuando moví la carpeta a un directorio local, el problema desapareció. parece que el Killed stop ocurrió durante las importaciones iniciales de mi biblioteca cuando recibí mensajes de bibliotecas faltantes una vez que moví la carpeta.

El problema desapareció después de reiniciar mi computadora.

Por lo tanto, es posible que las personas deseen intentar mover el programa a un directorio local si se trata de un recurso compartido de algún tipo o podría ser un problema transitorio que solo requiere reiniciar el sistema operativo.

  • Espera, ¿tuviste que reiniciar tu host o la VM?

    – cglacet

    16 oct 2020 a las 14:59

  • Reinicié la máquina virtual. El problema para mí ocurrió cuando estaba construyendo una nueva máquina virtual y acababa de instalar Python. Después de reiniciar la máquina virtual, el problema desapareció. Odio reiniciar como una forma de arreglar las cosas, así que pasé mucho tiempo tratando de depurar y después de una hora de excavación me rendí e hice el rebote.

    – Timothy C. Quinn

    10 de abril de 2021 a las 15:53

  • Espera, ¿tuviste que reiniciar tu host o la VM?

    – cglacet

    16 oct 2020 a las 14:59

  • Reinicié la máquina virtual. El problema para mí ocurrió cuando estaba construyendo una nueva máquina virtual y acababa de instalar Python. Después de reiniciar la máquina virtual, el problema desapareció. Odio reiniciar como una forma de arreglar las cosas, así que pasé mucho tiempo tratando de depurar y después de una hora de excavación me rendí e hice el rebote.

    – Timothy C. Quinn

    10 de abril de 2021 a las 15:53

¿Ha sido útil esta solución?