为什么这段代码会占用内存?当我运行它时,每个循环都会慢慢消耗更多的内存,而且我有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()
答案 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
本身就是一个非常大的对象,我不会感到惊讶。