使用Django的Python脚本中的明显内存泄漏

时间:2014-01-17 15:52:06

标签: python django memory-leaks out-of-memory

我有一个用于构建站点地图的脚本 - 对于每个相关模型,我生成了一些带有每个对象的URL的分页站点地图,每周我打算再次运行脚本用新数据重新生成站点地图。

然而,当我在我的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写入站点地图文件。写完这些后,我们关闭该文件并启动另一个文件。这种分页行为的原因是,当将所有条目写入一个文件时,我很快就达到了内存限制。这比以前更好,但是当我使用resource跟踪内存使用情况时,我可以看到它在每个文件写入后都会爬升。数据库中有大约200,000个这种类型的对象,所以理想情况下我需要尽可能地扩展它。但是我无法看到在主循环的每次迭代之后如何保持内存:在每次迭代之后重写QuerySet对象,并且在每次迭代之后关闭文件句柄并重新分配。我认为Python的GC行为将允许在重新分配变量后清除不再使用的对象。那不是这样吗?

1 个答案:

答案 0 :(得分:1)

The docs似乎暗示使用object.values_list('foreignobject__url')可以使用相关字段。因此,如果foreignobject是模型上的外键,其中包含字段url,则可以安全地使用values_list来减少数据库调用。