我有一個腳本,我正在使用它來構建一個站點地圖 - 對於每個相關模型,我生成了一些帶有每個對象的URL的分頁站點地圖,每個一週我打算再次運行該腳本以重新生成新數據的站點地圖。使用Django的Python腳本中的內存泄漏
但是,當我在我的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
來跟蹤內存使用情況時,我可以看到它在每個文件寫入後都在攀升。在數據庫中有大約20萬個這種類型的對象,所以理想情況下我需要儘可能地擴展它。但是我無法看到主循環的每次迭代之後內存如何保留:在每次迭代之後重寫對象QuerySet
,並且在每次迭代之後關閉並重新分配文件句柄。我認爲一旦變量被重新分配,Python的GC行爲將允許不再使用的對象被清除。情況並非如此嗎?
能'object.url()'做某事嗎?如果只用一組字符串替換django模型,並將其寫入文件,以查看模型或您的'xml_for_page'是否與它有任何關係,那該怎麼辦?繼續削減示例代碼,正如我所說 – TankorSmash
如果您要提高可伸縮性,爲什麼不在模型上使用'.defer'或'.only'或者甚至是'.values_list'?降低數據庫調用的數量越多越好。 – TankorSmash
'url()'函數在這裏限制了我 - 雖然我可以通過values_list獲取ID和last_modified_date,但url函數使用來自外鍵字段的值,所以我仍然需要獲取對象本身。或者是否有類似的函數來獲取某個特定成員函數的結果? – benwad