2013-10-04 88 views
42

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

而且Killedfinished counting打印完之后,情况发生,并且完整的消息是:

killed (program exited with code: 137) 
+6

后你所得到的错误消息的确切措辞。 –

+2

“遇难”通常意味着进程收到一些信号导致它退出。在这种情况下,由于它在脚本的同一时间发生,很可能它是一个破损的管道,该进程正在尝试读取或写入已在另一端关闭的文件句柄。 –

+1

这不是一个关于“杀死”消息来自哪里的答案,但是如果它是由于某种系统内存限制导致的,你可以通过使用'counter.iteritems()'而不是'counter .items()'在你的最后一个循环中。在Python 2中,'items'返回字典中键和值的列表,如果它非常大,则可能需要大量内存。相反,'iteritems'是一个发生器,在任何时候只需要少量的内存。 – Blckknght

回答

55

退出代码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

正确,但字典本身也会占用很多内存。 OP应该考虑逐步读取和处理文件,而不是一次全部处理文件。 – Kevin

2

我怀疑什么是杀害的过程,只是因为它需要一个长时间。一般来说,杀死意味着外部的东西终止了该进程,但可能不会在这种情况下击中Ctrl-C,因为这会导致Python退出KeyboardInterrupt异常。另外,在Python中,如果出现问题,您将得到MemoryError异常。可能发生的是你正在碰到Python或标准库代码中的一个错误,导致进程崩溃。

+0

一个崩溃的bug比获得'SIGKILL'更可能导致段错误,除非Python由于某种原因在其代码的某处出现'raise(SIGKILL)'。 – Kevin

14

存在两个存储区域:堆栈和堆栈。堆栈是保存方法调用当前状态的地方(即局部变量和引用),堆是存储对象的地方。recursion and memory

客串我中有counter字典,这将消耗堆区的内存太多太多的按键,让Python运行时将抛出一个内存溢出例外。

要保存它,请不要创建巨大的对象,例如计数器

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 

参考