当使用Python处理巨大的CSV突然停止时,“杀死”是什么意思?


89

我有一个Python脚本,该脚本导入一个大型CSV文件,然后计算该文件中每个单词的出现次数,然后将计数导出到另一个CSV文件。

但是发生的是,一旦计数部分完成并开始输出,它就会Killed在终端上说。

我不认为这是内存问题(如果是的话,我认为我会遇到内存错误而不是Killed)。

可能是这个过程花了太长时间吗?如果是这样,有没有办法延长超时期限,这样我可以避免这种情况?

这是代码:

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

而且Killed发生后finished counting已打印,以及完整的信息是:

killed (program exited with code: 137)

6
发布您收到的错误消息的确切措辞。
罗伯特·哈维

2
“已终止”通常表示该进程收到一些导致其退出的信号。在这种情况下,由于它是在脚本的同一时间发生的,因此很有可能是破损的管道,该进程试图读取或写入另一端已关闭的文件句柄。
安德鲁·克拉克

3
这不是有关killed消息来自何处的答案,但如果是由于超出某种系统内存限制counter.iteritems()而引起的counter.items(),则可以通过使用而不是在最终循环中解决此问题。在Python 2中,items返回字典中键和值的列表,如果它很大,可能会需要大量内存。相反,iteritems是在任何给定时间仅需要少量内存的生成器。
Blckknght

Answers:


101

退出代码137(128 + 9)表示您的程序由于接收到信号9而退出了SIGKILL。这也解释了该killed消息。问题是,您为什么收到该信号?

最可能的原因可能是您的进程超出了允许使用的系统资源量的某些限制。根据您的操作系统和配置,这可能意味着您有太多打开的文件,使用了过多的文件系统空间或其他东西。最有可能的是您的程序使用了过多的内存。当内存分配开始失败时,系统不会发出危险,而是向使用过多内存的进程发送终止信号。

如前所述,打印后您可能会达到内存限制的一个原因finished counting是,您counter.items()在最终循环中对的调用会分配一个列表,其中包含字典中的所有键和值。如果您的词典中有很多数据,那么这可能是一个很大的列表。一种可能的解决方案是使用counter.iteritems()哪个是发电机。无需返回列表中的所有项目,而是让您以更少的内存使用量对其进行迭代。

因此,建议您尝试此操作,作为您的最终循环:

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

请注意,在Python 3中,items返回的“字典视图”对象的开销与Python 2的版本不同。它取代了iteritems,因此,如果以后升级Python版本,最终将把循环改回原来的样子。


2
正确,但是字典本身也会占用大量内存。OP应该考虑增量读取而不是一次读取和处理文件。
凯文

24

其中涉及两个存储区域:堆栈和堆。堆栈是保存方法调用的当前状态(即局部变量和引用)的地方,而堆是存储对象的地方。递归和记忆

我猜想counter字典中有太多键会占用堆区域的太多内存,因此Python运行时将引发OutOfMemory异常。

要保存它,请不要创建一个巨大的对象,例如counter

1.StackOverflow

一个创建太多局部变量的程序。

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.内存不足

创建巨人的程序dict包含太多密钥。

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

参考文献

2

我怀疑是因为要花很长时间才能杀死进程。一般情况下,Kill意味着来自外部的某些东西终止了该进程,但在这种情况下,可能不会按Ctrl-C,因为那样会导致Python退出KeyboardInterrupt异常。另外,如果是这个问题,在Python中您将获得MemoryError异常。可能发生的情况是您遇到了Python或标准库代码中的错误,导致流程崩溃。


SIGKILL除非Pythonraise(SIGKILL)由于某种原因在代码中有某个地方,否则崩溃的bug更有可能导致段错误而不是得到段错误。
凯文

1
python中的错误不会发送SIGKILL。
qwr

2

您很可能用尽了内存,因此内核杀死了您的进程。

您听说过OOM Killer吗?

这是我为处理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

它取自/var/log/syslog

基本上:

PID 12216被选为受害者(由于使用了+ 9Gb的total-vm),因此oom_killer获得了它。

这是有关OOM行为的文章。


1
+1,只是为了澄清,要了解我的程序要使用多少RAM,我应该将total-vm,anon-rss,file-rss值相加吗?另外,total-vm给出了我的程序正在使用多少,而不是实际的可用内存,对吗?抱歉,知识有限。
momo

1
在这种情况下,我的知识也很有限@momo。我没有时间进行进一步调查,但是我发现这篇文章可能会有所帮助:stackoverflow.com/questions/18845857/…。我可以告诉您的是,确实,total-vm是该进程使用的内存量。
ivanleoncz

0

当我尝试VirtualBox从新的Ubuntu 20.04 LTS中的共享文件夹运行python脚本时,我也遇到了同样的情况。Killed在加载我自己的个人库时,Python获得了保释。当我将文件夹移动到本地目录时,问题就消失了。似乎Killed停止是在最初导入我的库的过程中发生的,因为一旦我将文件夹移开,我就会收到丢失库的消息。

重新启动计算机后,问题消失了。

因此,人们可能想尝试将程序移到本地目录(如果它在某种程度上超过共享),或者可能是暂时的问题,只需要重新启动操作系统即可。


等待,您必须重新启动主机或VM?
cglacet

是。就我而言,我正在构建一个新的VM,并且在看到此问题时刚刚安装了Python。重新启动后,它消失了。我讨厌重启作为修复问题的一种方式,因此我花了很多时间尝试调试,并且经过一个小时的挖掘,包括SO中的内容。但是最终,我放弃了,重新启动并保存了。我不知道它为什么起作用。
Timothy C. Quinn
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.