当用Python处理一个巨大的CSV时,它突然停止了,“killed”是什么意思?

问题描述 投票:0回答:6

我有一个 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)
python csv etl kill
6个回答
145
投票

退出代码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 版本,您最终会将循环更改回原来的方式。


36
投票

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

我猜测

counter
字典中的键太多,会消耗太多堆区域的内存,因此 Python 运行时会引发 OutOfMemory 异常。

为了保存它,不要创建一个巨大的对象,例如柜台

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

参考文献


7
投票

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

你听说过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 的总虚拟机),因此 oom_killer 收获了它。

这是一篇关于 OOM 行为的文章。


5
投票

我怀疑有什么东西会杀死这个过程,只是因为它需要很长时间。 Killed 通常意味着来自外部的某些东西终止了进程,但在本例中可能不是按 Ctrl-C,因为这会导致 Python 在键盘中断异常时退出。另外,在 Python 中,如果这是问题所在,你会得到 MemoryError 异常。可能发生的情况是您遇到了 Python 或标准库代码中的错误,导致进程崩溃。


4
投票

当我尝试从新的 Ubuntu 20.04 LTS 中的

VirtualBox
中的共享文件夹运行 python 脚本时,我也遇到了同样的情况。 Python 在加载我自己的个人库时使用
Killed
进行了退出。当我将文件夹移动到本地目录时,问题就消失了。看来
Killed
停止发生在我的库的初始导入期间,因为一旦我将文件夹移动过来,我就收到了缺少库的消息。

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

因此,如果程序位于某种共享上,或者可能是一个暂时性问题,只需要重新启动操作系统,人们可能会尝试将程序移动到本地目录。


0
投票

我遇到了类似的问题,进程正在退出,代码为 137,但我运行的脚本并没有消耗大量内存来导致 OOM Killed。结果我使用的 Python 解释器已损坏,因此必须完全删除该安装并重新安装一个。

© www.soinside.com 2019 - 2024. All rights reserved.