【问题标题】:Make python generator run in background让python生成器在后台运行
【发布时间】:2018-03-09 02:55:33
【问题描述】:

现在我有一些代码大致执行以下操作

def generator():

    while True:
        value = do_some_lengthy_IO()
        yield value 

def model():

    for datapoint in generator():
        do_some_lengthy_computation(datapoint)

现在,I/O 和计算是串行发生的。理想情况下,应该同时运行并行(生成器已经准备好下一个值),因为它们只共享传递的值。我开始研究这个并且对multiprocessingthreadingasync 的东西感到非常困惑,并且无法得到一个最小的工作示例。此外,由于其中一些似乎是最近的功能,所以我使用的是 Python 3.6。

【问题讨论】:

  • 如果你在python3.5+,你可以看看asyncIO。对于旧版本,可以使用队列进行多处理。
  • 恕我直言,这是一个经典的“just”-[CONCURRENT] 进程调度,到目前为止不是真正的- [PARALLEL] processing 系统,请查看帖子>>> stackoverflow.com/revisions/8337936/4 并可能希望修改/编辑已声明的问题公式,以更好地满足计算机科学与复杂系统和进程调度术语。
  • 给我们一个简单的、独立的、完整的例子,而不是一个模糊的伪例子。如所问,这个问题过于宽泛,无法以这种格式合理回答。

标签: python asynchronous concurrency multiprocessing


【解决方案1】:

我最终弄明白了。最简单的方法是使用multiprocessing 包并使用管道与子进程通信。我写了一个可以带任何生成器的包装器

import time
import multiprocessing

def bg(gen):
    def _bg_gen(gen, conn):
        while conn.recv():
            try:
                conn.send(next(gen))
            except StopIteration:
                conn.send(StopIteration)
                return

    parent_conn, child_conn = multiprocessing.Pipe()
    p = multiprocessing.Process(target=_bg_gen, args=(gen, child_conn))
    p.start()

    parent_conn.send(True)
    while True:
        parent_conn.send(True)
        x = parent_conn.recv()
        if x is StopIteration:
            return
        else:
            yield x

def generator(n):
    for i in range(n):
        time.sleep(1)
        yield i

#This takes 2s/iteration
for i in generator(100):
    time.sleep(1)

#This takes 1s/iteration
for i in bg(generator(100)):
    time.sleep(1)

现在唯一缺少的是,对于无限生成器,进程永远不会被杀死,但可以通过 parent_conn.send(False) 轻松添加。

【讨论】:

    猜你喜欢
    • 2017-07-09
    • 1970-01-01
    • 2015-01-13
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-28
    相关资源
    最近更新 更多