Python 3.8异步并发编程指南( 五 )


但想象一下,我们有一个真正缓慢的操作发生,这意味着任务没有完成,当我们检查future.done() 。
在这种情况下,我们应该注意,调用.shutdown()的位置是在我们明确等待计划的任务完成之前,然而当我们断言返回的future是否.done()返回时,我们会发现,无论尝试关闭线程池,任务都标记为"已完成" 。
这是因为关闭方wait=True法的默认行为意味着它将等待所有计划的任务完成,然后再关闭执行器池 。
因此,该方法是同步调用.shutdown()(即,它确保所有任务在关闭之前都已完成,因此我们可以保证所有结果都可用) 。
如果我们传递.shutdown(wait=False)相反,那么调用future.done()将引发一个异常(因为计划的任务仍将在线程池关闭时运行),因此在这种情况下,我们需要确保我们使用另一种机制来获取计划任务的结果(如 concurrent.futures.as_completed或concurrent.futures.wait ) 。
asyncio.Future和concurrent.futures.Future最后一点要提的是,concurrent.futures.Future对象与asyncio.Future
不同 。asyncio.Future用于异步事件循环,并且可等待 。concurrent.futures.Future不可等待 。
使用事件循环的.run_in_executor()方法将通过将concurrent.futures.Future类型包装到asyncio.wrap_future(有关详细信息,请参阅下一节)来提供两种未来类型之间的必要互操作性 。
asyncio.wrap_future由于 Python 3.5,我们可以使用asyncio.wrap_future 将 concurrent.futures.Futur转换为easyncio.Future。下面可以看到这方面的示例...
import asyncioimport randomfrom concurrent.futures import ThreadPoolExecutorfrom time import sleepdef return_after_5_secs(message):sleep(5)return messagepool = ThreadPoolExecutor(3)async def doit():identify = random.randint(1, 100)future = pool.submit(return_after_5_secs, (f"result: {identify}"))awaitable = asyncio.wrap_future(future)print(f"waiting result: {identify}")return await awaitableasync def app():# run some stuff multiple timestasks = [doit(), doit()]result = await asyncio.gather(*tasks)print(result)print("waiting app")asyncio.run(app())此程序的输出将是:
waiting appwaiting result: 62waiting result: 83# ...five seconds pass by...['result: 62', 'result: 83']



推荐阅读