为什么这个Python(Django)代码会占用内存?

时间:2010-07-16 19:18:06

标签: python django

为什么这段代码会占用内存?当我运行它时,每个循环都会慢慢消耗更多的内存,而且我有300000个循环。我正在使用Windows和Python 2.6。

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()

4 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:2)

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

此外,根据您拥有的投票比LegacyUserId或LegacyMedia行多多少,如果您有外键,您可能只考虑通过连接直接选择这些行,而不是通过投票然后发出新查询id存在。

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

答案 2 :(得分:1)

您永远不会关闭您打开的文件。您应该像这样进行文件访问

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

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

答案 3 :(得分:0)

大概是因为它为数据库中的每个Vote加载对象,然后迭代这些投票并为每个投票加载LegacyUserId,并为每个投放LegacyMedia个对象。

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

如果LegacyMedia本身就是一个非常大的对象,我不会感到惊讶。