我目前有一个生成器形式的代码,它调用IO绑定任务。生成器实际上也调用了子生成器,因此可以理解更通用的解决方案。
如下所示:
def processed_values(list_of_io_tasks):
for task in list_of_io_tasks:
value = slow_io_call(task)
yield postprocess(value) # in real version, would iterate over
# processed_values2(value) here
我完全控制slow_io_call
,我不关心从processed_values
获取项目的顺序。有没有像coroutines这样的东西可以通过将slow_io_call
转换为异步函数并使用哪个调用返回最快来以最快的顺序获得结果?我希望list_of_io_tasks
至少有数千个条目。除了使用显式线程之外,我从未做过任何并行工作,特别是我从未使用过各种形式的轻量级线程。
我需要使用标准的CPython实现,而我正在Linux上运行。
答案 0 :(得分:2)
听起来您正在寻找multiprocessing.Pool(),特别是Pool.imap_unordered()方法。
这是函数的一个端口,它使用imap_unordered()来并行化对slow_io_call()的调用。
def processed_values(list_of_io_tasks):
pool = multiprocessing.Pool(4) # num workers
results = pool.imap_unordered(slow_io_call, list_of_io_tasks)
while True:
yield results.next(9999999) # large time-out
请注意,您也可以在没有results
循环的情况下直接迭代for item in results: yield item
(例如while True
),但是使用超时值调用results.next()
可以解决此问题{ {3}}并允许您使用Ctrl-C终止主进程和所有子进程。另请注意,此函数中未捕获StopIteration异常,但当results.next()
没有更多项返回时,将引发一个异常。这对于生成器函数是合法的,例如这个函数,当没有更多的值可以产生或者只是停止让步时,它们会引发StopIteration错误,代表它会引发StopIteration异常。
要使用线程代替进程,请替换
import multiprocessing
与
import multiprocessing.dummy as multiprocessing