2010-07-16 26 views
2

为什么这段代码吃掉了内存?当我运行它时,它每次循环都会消耗更多的内存,并且我拥有300000个循环。我使用Windows和Python 2.6。为什么这个Python(Django)代码吃掉了内存?

def LoadVotes(self): 
    old_votes=Votes.objects.all() 
    amount=old_votes.count() 
    print 'Amount of votes is: ' + str(amount) 
    c=0 
    for row in old_votes: 
     try: 
      new_id_user=LegacyUserId.objects.get(legacy_id=row._login) 
     except LegacyUserId.DoesNotExist: 
      string=" user with old id "+str(row._login)+" does not match new user id /n" 
      log=open('log_add_old_votes.txt','a') 
      log.write(string) 
      continue 
     try: 
      new_id_media=LegacyMedia.objects.get(legacy_id=row.media_file_id) 
     except new_id_media.DoesNotExist: 
      log_text='old media with ID:'+str(row.media_file_id)+' is not found in relation with new media \n' 
      log=open('log_add_old_votes.txt','a') 
      log.write(log_text) 
      continue 
     mo=MediaObject.objects.get(pk=new_id_media.object_id) 
     new_votes_item, created=Mark.objects.get_or_create(user=new_id_user.user, media_object=mo, defaults={'mark':int(row.rate)*2}) 
     c=c+1 
     i=amount-c 
     print '\rRemain:', 
     stdout.write("%d" % i) 
     stdout.flush() 
+1

从底部开始,一次删除一行(您可以使用二进制搜索来加速该错误),直到问题消失。应该很容易找出哪条线正在吃掉记忆。 – Brian 2010-07-16 19:25:10

回答

5

如果使用DEBUG = True运行,则django会将所有查询存储在内存中。尝试在settings.py文件中更改为DEBUG = False。

+0

你对调试=真 – Pol 2010-07-16 19:33:05

+0

谢谢!你是对的。它成为调试=尝试 – Pol 2010-07-16 21:21:43

0

大概是因为它加载的每Vote对象在数据库中,然后通过这些票和加载LegacyUserId S表示每一个迭代,并为每一个LegacyMedia对象。

如果您拥有的数据量很大,或者这些对象很大,则会占用大量内存。

我不会惊讶,如果LegacyMedia本身是一个很大的对象。

+1

YE但每个循环都必须清除变量。相反,它正在降我的记忆。也许这是因为我没有关闭日志文件和每个循环它再次打开文件,并采取莫内存它? 我没有使用log.close() – Pol 2010-07-16 19:30:11

1

你永远不会关闭你打开的文件。你应该这样做文件访问

with open('log_add_old_votes.txt','a') as log: 
    log.write(string) 

这将自动关闭文件对象,为你一旦你完成它。您还将为每条日志消息使用相同的文件,因此您可以将open移至循环前面并在完成之前使用同一个文件对象。

2

我不确定Vote模型是什么样子。但是你只对来自投票(_login和media_file_id)的两个属性感兴趣。因此,您可以考虑使用值或values_list查询集API - 这样您只需选择所需的字段,并且不会为每行创建一个对象。

另外,根据您拥有的LegacyUserId或LegacyMedia行数量多少,如果您有外键,您可以考虑直接通过连接选择这些行,而不是迭代投票,然后在发出新查询时发出新的查询ID的存在。

最后,这不会影响内存,但考虑使用python logging而不是当前的方法。 (或者至少在函数启动时打开文件一次,而不是每次需要写入时)。

+0

我没有关系我的数据库(没有外键)。那就是为什么我要制作我需要的每个模型的实例。 你说得对。我改变了我的代码。现在我正在探索如何使用日志记录。 – Pol 2010-07-16 21:25:52

+0

问题是whith DEBUG = True。但无论如何谢谢你。 – Pol 2010-07-16 21:26:53