我有一个用于构建站点地图的脚本 - 对于每个相关模型,我生成了一些带有每个对象的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行为将允许在重新分配变量后清除不再使用的对象。那不是这样吗?
答案 0 :(得分:1)
The docs似乎暗示使用object.values_list('foreignobject__url')
可以使用相关字段。因此,如果foreignobject
是模型上的外键,其中包含字段url
,则可以安全地使用values_list
来减少数据库调用。