2014-01-17 4 views
2

У меня есть сценарий, который я использую для создания файла Sitemap. Для каждой из соответствующих моделей я создаю несколько постраничных карточек с URL для каждого объекта, и каждый неделю Я намерен снова запустить сценарий, чтобы восстановить карту сайта со свежими данными.Видимая утечка памяти в скрипте Python с использованием Django

Однако, когда я запускаю этот скрипт на своем сервере Ubuntu, использование памяти продолжает расти, пока процесс не будет уничтожен ОС. Вот функция, я в настоящее время возникают проблемы при получении через:

def xml_for_page(object): 
    sOutText = "\t<url>\n" 

    sURL = object.url() 
    sOutText += "\t\t<loc>http://www.mysite.com%s</loc>\n" % sURL 

    sLastModified = object.last_status_change.isoformat() 
    sOutText += "\t\t<lastmod>%s</lastmod>\n" % sLastModified 

    sChangeFreq = "monthly" 
    sOutText += "\t\t<changefreq>%s</changefreq>\n" % sChangeFreq 

    sOutText += "\t</url>\n" 

    return sOutText 

def generate_object_map(): 

    # Do this in chunks of ITEMS_PER_FILE 
    bFinished = False 
    iOffset = 0 
    iCurrentPage = 0 

    while not bFinished: 
     objResults = PageObject.objects.filter(submission_status=SUBMISSION_STATUS_ACCEPTED).order_by('-popularity')[iOffset:iOffset+ITEMS_PER_FILE] 
     if objResults.count() < 1: 
      break 
     sFilename = "%s/sitemap-objects-%i.xml" % (OUTPUT_DIR, iCurrentPage) 
     fObjects = open(sFilename, 'w') 
     fObjects.write('<?xml version="1.0" encoding="UTF-8"?>\n') 
     fObjects.write('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n') 
     for object in objResults: 
      fObjects.write(xml_for_page(object)) 
     fObjects.write('</urlset>') 
     fObjects.close() 
     iOffset += ITEMS_PER_FILE 
     iCurrentPage += 1 

Так что же здесь происходит: при каждой итерации цикла while not bFinished мы создаем новый файл для страницы, мы на, и запрос к базе данных для этот конкретный набор объектов. Затем мы перебираем эти объекты и записываем XML для этой страницы в файл Sitemap. Как только они написаны, мы закрываем этот файл и запускаем другой. Причиной этого поведения подкачки является то, что при записи всех записей в один файл я быстро ударяю по памяти. Это ведет себя лучше, чем это было тогда, но когда я использую resource для отслеживания использования памяти, я вижу, как он поднимается после каждого записанного файла. В базе данных около 200 000 объектов этого типа, поэтому в идеале мне нужно сделать это максимально масштабируемым. Однако я не вижу, как память хранится после каждой итерации основного цикла: объект QuerySet переписывается после каждой итерации, а дескриптор файла закрывается и перераспределяется после каждой итерации. Я думал, что поведение GC на Python позволит очищать ненужные объекты после того, как переменная была перераспределена. Разве это не так?

+0

Может ли 'object.url()' что-то делать? Что делать, если вы заменили модели django только набором строк и вместо этого написали это в файл, чтобы увидеть, имеет ли это модели или ваша «xml_for_page». Продолжайте сокращать примерный код, это то, что я говорю – TankorSmash

+0

Если вы собираетесь использовать масштабируемость, почему бы не использовать в своих моделях '.defer' или' .only' или даже '.values_list'? Чем меньше количество звонков, тем лучше. – TankorSmash

+0

Функция 'url()' - это то, что меня ограничивает здесь, - хотя я мог бы получить идентификатор и 'last_modified_date' через' values_list', функция 'url' использует значения из полей внешнего ключа, поэтому мне все равно придется извлекать объект сам. Или существует аналогичная функция для получения результатов одной конкретной функции-члена? – benwad

ответ

1

The docs, по-видимому, предполагает, что было бы хорошо использовать object.values_list('foreignobject__url'), что позволит связать поля. Поэтому, если foreignobject является внешним ключом на вашей модели, который сам содержит поле url, вы можете быть безопасным использовать values_list, чтобы уменьшить количество вызовов БД.

Смежные вопросы