暂停Python生成器

时间:2011-08-09 19:36:40

标签: python generator

我有一个python生成器,可以生成大量数据,占用大量内存。有没有办法检测处理过的数据是否已被使用生成器的代码“消耗”,如果是,请暂停直到它被消耗?

def multi_grab(urls,proxy=None,ref=None,xpath=False,compress=True,delay=10,pool_size=50,retries=1,http_obj=None):
    if proxy is not None:
        proxy = web.ProxyManager(proxy,delay=delay)
        pool_size = len(pool_size.records)
    work_pool = pool.Pool(pool_size)
    partial_grab = partial(grab,proxy=proxy,post=None,ref=ref,xpath=xpath,compress=compress,include_url=True,retries=retries,http_obj=http_obj)
    for result in work_pool.imap_unordered(partial_grab,urls):
        if result:
            yield result

从:

开始
if __name__ == '__main__':
    links = set(link for link in grab('http://www.reddit.com',xpath=True).xpath('//a/@href') if link.startswith('http') and 'reddit' not in link)
    print '%s links' % len(links)
    counter = 1
    for url, data in multi_grab(links,pool_size=10):
        print 'got', url, counter, len(data)
        counter += 1

4 个答案:

答案 0 :(得分:8)

生成器只会产生值。生成器无法知道它们正在做什么。

但是生成器也会不停地停顿,因为调用者会做任何事情。在调用者调用它以获取下一个值之前,它不会再次执行。它不会在单独的线程或任何东西上运行。听起来你对发电机的运行方式存在误解。你能展示一些代码吗?

答案 1 :(得分:2)

Python中生成器的要点是在每次迭代后摆脱额外的,不需要的对象。唯一一次它将保留那些额外的对象(以及额外的ram)是在其他地方引用对象时(例如将它们添加到列表中)。确保您没有不必要地保存这些变量。

如果您正在处理多线程/处理,那么您可能希望实现一个可以从中提取数据的队列,并跟踪您正在处理的任务数量。

答案 2 :(得分:0)

我认为您可能正在寻找yield功能。在另一个StackOverflow问题中解释:What does the "yield" keyword do in Python?

答案 3 :(得分:0)

解决方案可以是使用生成器将添加数据的Queue,而代码的另一部分将从中获取数据并对其进行处理。这样,您可以确保内存中的项目不超过n