我有一个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)
答案 0 :(得分:75)
退出代码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版本,您最终会将循环更改回原来的状态。
答案 1 :(得分:19)
涉及两个存储区:堆栈和堆。堆栈是保存方法调用的当前状态(即局部变量和引用)的位置,堆是存储对象的位置。 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
参考
答案 2 :(得分:4)
您很有可能用完了内存,因此内核杀死了您的进程。
您听说过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 behavior的文章。
答案 3 :(得分:3)
我怀疑是因为需要很长时间才能杀死这个过程。杀死一般意味着来自外部的东西终止了进程,但在这种情况下可能不会按Ctrl-C,因为这会导致Python退出KeyboardInterrupt异常。此外,在Python中,如果出现问题,您将获得MemoryError异常。可能发生的事情是你遇到了Python或标准库代码中导致进程崩溃的错误。
答案 4 :(得分:0)
当我尝试从新的Ubuntu 20.04 LTS的VirtualBox
中的共享文件夹运行python脚本时,我也遇到了同样的情况。在加载我自己的个人库时,Python用Killed
进行了保释。当我将文件夹移动到本地目录时,问题就消失了。似乎Killed
停止发生在我的库的最初导入过程中,因为一旦将文件夹移到我之后,我收到丢失库的消息。
重新启动计算机后,问题消失了。
因此,人们可能希望尝试将程序移至本地目录(如果存在某种共享),或者这可能是短暂的问题,只需要重新启动操作系统即可。