我有一个python脚本,可以抓取一些网址。我有一个网址列表,每个网址我都得到了html,并用它做了一些逻辑。
我使用Python 2.7.6和Linux Mint 17 Cinnamon 64位。
问题是我的主要抓取对象(我为每个url实例化)从不从内存中释放,尽管没有引用它。有了这个问题,我的记忆就会不断增长和快速增长(因为我的目标有时非常大 - 高达50MB)。
简化代码看起来像这样:
def scrape_url(url):
"""
Simple helper method for scraping url
:param url: url for scraping
:return: some result
"""
scraper = Scraper(url) # instance main Scrape object
result = scraper.scrape() # scrape it
return result
## SCRIPT STARTS HERE
urls = get_urls() # fetch some list of urls
for url in urls:
print 'MEMORY USAGE BEFORE SCRAPE: %s (kb)' % resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
result = scrape_url(url) # call helper method for scraping
print 'MEMORY USAGE AFTER SCRAPE: %s (kb)' % resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
print '-' * 50
我的输出是这样的:
MEMORY USAGE BEFORE SCRAPE: 75732 (kb)
MEMORY USAGE AFTER SCRAPE: 137392 (kb)
--------------------------------------------------
MEMORY USAGE BEFORE SCRAPE: 137392 (kb)
MEMORY USAGE AFTER SCRAPE: 206748 (kb)
--------------------------------------------------
MEMORY USAGE BEFORE SCRAPE: 206748 (kb)
MEMORY USAGE AFTER SCRAPE: 284348 (kb)
--------------------------------------------------
Scrape对象很大,并且不会从内存中释放。 我试过了:
scraper = None
del scraper
甚至调用gc来收集对象:
gc.collect()
但没有任何帮助。
当我打印刮刀对象的参考数量时:
print sys.getrefcount(scraper)
我得到 2 ,我认为这意味着没有其他对象的引用,应该用gc清理。
Scraper对象有很多子对象。是否有可能某些子对象的引用被遗留在某处,因此gc无法释放主Scaper对象,或者还有其他原因导致python不释放内存?
我在SO中找到了一些关于此问题的主题以及他们所说的内容无法释放的一些回复,除非你产生/杀死听起来很奇怪的子进程(LINK)
谢谢, 伊万
答案 0 :(得分:1)
您正在使用迭代器,它必须始终在内存中。 重写你的循环使用发电机和懒惰刮。有点像:
def gen():
for i in xrange(0, len(urls)):
yield urls[i]