【问题标题】:Pause Python Generator暂停 Python 生成器
【发布时间】:2011-10-23 12:49:45
【问题描述】:

我有一个 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

【问题讨论】:

  • 您必须向我们展示代码。但是生成器只有在调用next() 方法时才能工作;它们无法自行生产,因此解决方案是让迭代它们的任何东西消耗它们停止,直到它们消耗掉它们已经摄取的东西。

标签: python generator


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

        • github.com/mattseh/python-web/blob/master/web.py multi_grab 方法和 if name == 'main' 下的示例:我正在使用另一个生成器 (work_pool.imap_unordered) ,它使用线程(greenlets)。
        • gevent 将异步 (!) 引入您的代码,并且这些线程能够独立于调用者拉取值而工作。我不确定如何最好地获得您需要的效果。
        • 看来我需要创建自己的 imap_unordered 版本。感谢您的意见!
        猜你喜欢
        • 2018-12-19
        • 2016-09-18
        • 1970-01-01
        • 1970-01-01
        • 2021-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多