在同步线程中使用的run_in_executor就如它方法的名字所示,把协程放到了一个执行器里面,可以在一个线程池,也可以在一个进程池。另外还可以使用run_coroutine_threadsafe在其他线程执行协程(这是线程安全的)。
多线程
def start_loop(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
def shutdown(loop):
loop.stop()
async def b1():
new_loop = asyncio.new_event_loop()
t = Thread(target=start_loop, args=(new_loop,))
t.start()
future = asyncio.run_coroutine_threadsafe(a(), new_loop)
print(future)
print(f'Result: {future.result(timeout=2)}')
new_loop.call_soon_threadsafe(partial(shutdown, new_loop))
In : await b1()
<Future at 0x107edf4e0 state=pending>
Result: A
这里面有几个细节要注意:
应该从另一个线程调用协程,而不是运行事件循环的线程,因此使用 asyncio.new_event_loop() 创建一个新的事件循环
确保新创建的事件循环在执行协程之前正在运行,因此你需要使用 start_loop 之类的东西来启动循环
接着就可以用asyncio.run_coroutine_threadsafe执行协程a了,它返回了一个Future对象
通过输出可以感觉到一开始future是pending的,因为协程a会在返回结果之前休眠1秒
使用future.result(timeout=2)获取结果,设置timeout的值大于协程的执行时间,否则会抛出TimeoutError
一开始,我们创建的新事件循环在一个线程中运行。由于loop.run_forever会阻塞程序关闭,所以我们需要在最后杀死线程,所以使用call_soon_threadsafe回调函数shutdown来停止事件循环
让我们在这里再次谈谈 call_soon_threadsafe。从名字可以看出它是 call_soon 的线程安全版本,实际上是在另一个线程中调度回调。 BTW,其实asyncio.run_coroutine_threadsafe的底层也用到了。
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ python检查一个数字是否是素数08/14
- ♥ 如何启动python08/12
- ♥ python上下文管理器如何解决异常?12/30
- ♥ python命令行模式的使用过程09/28
- ♥ python文件名通常以什么结尾11/20
- ♥ Python itertools模块:生成迭代器(案例分析)12/10
内容反馈