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

l0oc07j2  于 12个月前  发布在  Python
关注(0)|答案(6)|浏览(229)

我有一个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)

4xy9mtcn

4xy9mtcn1#

退出代码137(128+9)表示程序由于接收到信号9(SIGKILL)而退出。这也解释了killed消息。问题是,为什么会收到这个信号?
最可能的原因可能是您的进程超过了允许使用的系统资源量的限制。根据您的操作系统和配置,这可能意味着您打开了太多的文件,使用了太多的文件系统空间或其他原因。最可能的原因是您的程序使用了太多的内存。当内存分配开始失败时,系统向使用过多内存的进程发送了一个kill信号。
正如我之前评论的,在打印finished counting后可能会达到内存限制的一个原因是,在最后一个循环中对counter.items()的调用分配了一个包含字典中所有键和值的列表。如果字典有很多数据,这可能是一个非常大的列表。一个可能的解决方案是使用counter.iteritems(),它是一个生成器。而不是返回列表中的所有项目,它可以让你用更少的内存来覆盖它们。
所以,我建议你试试这个,作为你的最后一个循环:

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

字符串
注意,在Python 3中,items返回一个“字典视图”对象,它没有Python 2版本的开销。它取代了iteritems,所以如果你以后升级Python版本,你最终会把循环改回原来的样子。

gojuced7

gojuced72#

有两个存储区域:栈和堆。栈是保存方法调用的当前状态的地方(即局部变量和引用),堆是存储对象的地方。recursion and memory
我猜counter dict中有太多的键,这将消耗堆区域的太多内存,因此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.OutOfMemory
创建巨大的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

引用

zzzyeukh

zzzyeukh3#

最有可能的是,你的内存用完了,所以内核杀死了你的进程。
你听说过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 behavior的文章。

nhaq1z21

nhaq1z214#

我怀疑有什么东西只是因为它需要很长时间就杀死了进程。杀死一般意味着外部的东西终止了进程,但在这种情况下可能不是按Ctrl-C,因为这会导致Python在键盘异常时退出。此外,在Python中,你会得到MemoryError异常,如果这是问题的话。可能发生的是你遇到了Python或标准库代码中的一个bug,导致进程崩溃。

qpgpyjmq

qpgpyjmq5#

当我试图在新的Ubuntu 20.04 LTS中的VirtualBox共享文件夹中运行Python脚本时,我也遇到了同样的情况。Python在加载我自己的个人库时用Killed进行了保释。当我将文件夹移动到本地目录时,这个问题消失了。看起来Killed停止发生在我的库的初始导入过程中,因为一旦我移动文件夹,我就会收到丢失库的消息。
这个问题在我重新启动电脑后就消失了。
因此,人们可能想尝试将程序移动到本地目录,如果它在某种共享上,或者它可能是一个暂时的问题,只需要重新启动操作系统。

bfrts1fy

bfrts1fy6#

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

相关问题