python异步编程案例之事件循环

先定义一个协程函数

import asyncio

async def do_some_work(x):
    print("Hello:",x)
    return "work is done for {}".format(x)

拿到事件循环对象loop容器,将协程对象扔进事件循环对象中触发。

coroutine = do_some_work('test')
loop = asyncio.get_event_loop()
loop.run_until_complete(coroutine)

run_until_complete 是一个阻塞(blocking)调用,直到协程运行结束,它才返回。

Hello: test

实际项目中,往往有多个协程,同时在一个 loop 里运行。为了把多个协程交给 loop实现并发,需要借助 asyncio.gather 或者 asyncio.wait函数。

coroutines = []
for i in range(5):
    coroutines.append(do_some_work(i))
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(coroutines))
# loop.run_until_complete(asyncio.gather(*coroutines))
Hello: 4
Hello: 0
Hello: 1
Hello: 2
Hello: 3

如何停止loop?
需要调用loop.stop(), 利用回调函数实现。

import asyncio
import functools

async def do_some_work(x):
    print("Hello:",x)
    return "work is done for {}".format(x)
    
def done_callback(loop, future):
    loop.stop()
    print("callback: ", future.result())
    
loop = asyncio.new_event_loop() # 创建一个新的loop对象
asyncio.set_event_loop(loop)
futus = asyncio.gather(do_some_work(1), do_some_work(2), do_some_work(3))
futus.add_done_callback(functools.partial(done_callback, loop))
loop.run_forever() #  在调用 stop() 之前将一直运行,restart loop
Hello: 1
Hello: 3
Hello: 2
callback:  ['work is done for 1', 'work is done for 2', 'work is done for 3']

彻底关闭loop
以上示例都没有调用 loop.close,好像也没有什么问题。所以到底要不要调 loop.close 呢?
简单来说,loop 只要不关闭,就还可以再运行。
继续运行以下代码。

loop.run_until_complete(do_some_work(4))
Hello: 4
Out[38]: 'work is done for 4'

但是如果关闭了,就不能再运行其他协程了。

loop.close()
loop.run_until_complete(do_some_work(5))
Traceback (most recent call last):
  File "D:\anaconda3\envs\tensor-flow\lib\site-packages\IPython\core\interactiveshell.py", line 3291, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-41-50fd63fec95a>", line 1, in <module>
    loop.run_until_complete(do_some_work(5))
  File "D:\anaconda3\envs\tensor-flow\lib\asyncio\base_events.py", line 460, in run_until_complete
    self._check_closed()
  File "D:\anaconda3\envs\tensor-flow\lib\asyncio\base_events.py", line 377, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

建议调用 loop.close,以彻底清理 loop 对象防止误用。

发布了24 篇原创文章 · 获赞 0 · 访问量 898

猜你喜欢

转载自blog.csdn.net/HighDS/article/details/103901008
今日推荐