如何使 Python 生成器异步执行?

How to make a Python generator execution asynchronous?

我有一段代码如下所示:

def generator():
    while True:
        result = very_long_computation()
        yield result

def caller():
    g = generator()
    for i in range(n):
        element = next(g)
        another_very_long_computation()

基本上,我想尽可能地重叠 very_long_computation()another_very_long_computation() 的执行。

有没有简单的方法让生成器异步?我希望生成器在生成 result 之后立即开始计算 while 循环的下一次迭代,这样(理想情况下)下一个 result 就可以在后续 [=16] 之前生成=] 调用 caller().

没有简单的方法,特别是因为您有 very_long_computationanother_very_long_computation 而不是 very_slow_io。即使您将 generator 移动到它自己的线程中,您也会受到 CPython 的全局解释器锁的限制,从而无法获得任何性能优势。

您可以将工作转移到工作进程中,但 multiprocessing 模块并不是它喜欢伪装的 threading 的直接替代品。它充满了奇怪的复制语义、不直观的限制和依赖于平台的行为,以及大量的通信开销。

如果您在计算的同时得到了 I/O,那么将生成器的工作推到它自己的线程中以至少在 I/O 期间完成一些工作是相当简单的:

from queue import Queue
import threading

def worker(queue, n):
    gen = generator()
    for i in range(n):
        queue.put(next(gen))

def caller():
    queue = Queue()
    worker_thread = threading.Thread(worker, args=(queue, n))
    worker_thread.start()
    for i in range(n):
        element = queue.get()
        another_very_long_computation()