【发布时间】:2016-05-22 10:44:11
【问题描述】:
我有一个可以抓取一些 url 的 python 脚本。我有一个 url 列表,对于每个 url,我得到 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)
谢谢, 伊万
【问题讨论】:
-
"Scraper 对象有很多子对象...不释放内存?"这将是唯一合理的理由。抓取网址在我假设的端口上建立了连接?可能该连接具有常设参考。
-
你确定这个结果和scraper没有关联吗?
标签: python memory memory-leaks garbage-collection