Почему этот код Python (Django) поглощает память? - PullRequest
2 голосов
/ 16 июля 2010

Почему этот код пожирает память? Когда я запускаю его, он медленно потребляет больше памяти с каждым циклом, и у меня получается что-то вроде 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 ]

5 голосов
/ 16 июля 2010

Если вы запускаете с DEBUG = True, django сохраняет все запросы в памяти. Попробуйте изменить на DEBUG = False в файле settings.py.

2 голосов
/ 16 июля 2010

Я не уверен, как выглядит модель голосования.Но вас интересуют только два атрибута голосования (_login и media_file_id).Таким образом, вы можете рассмотреть возможность использования значений или values_list queryset API - таким образом, вы выбираете только те поля, которые вам нужны, и не создаете объект для каждой строки.

Кроме того,В зависимости от того, сколько у вас голосов, чем у строк LegacyUserId или LegacyMedia, если у вас есть внешний ключ, вы можете просто рассмотреть возможность выбора этих строк непосредственно через объединение, а не итерацию голосов и последующую выдачу новых запросов, когда идентификатор существует.

Наконец, это не сильно повлияет на память, но рассмотрите возможность использования python logging вместо текущего метода.(Или, по крайней мере, открывайте файл один раз в начале функции, а не каждый раз, когда вам нужно написать.)

1 голос
/ 16 июля 2010

Вы никогда не закрываете открываемые файлы.Вы должны делать доступ к файлу следующим образом:

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

Это автоматически закроет объект файла для вас, как только вы закончите с ним.Вы также используете один и тот же файл для каждого сообщения журнала, так что вы можете переместить открытие до цикла и использовать один и тот же объект файла, пока не закончите.

0 голосов
/ 16 июля 2010

Предположительно, потому что он загружает объекты для каждого Vote в вашей базе данных, а затем перебирает эти голоса и загружает LegacyUserId с для каждого и LegacyMedia объектов для каждого.

Если объем данных у вас большой или эти объекты велики, это займет много памяти.

Я бы не удивился, если бы LegacyMedia был довольно большим объектом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...