loop除了处理协程间的切换与结束时的异常捕捉,还要监听socket和文件描述符。先作个小测试:bash
>>> import asyncio >>> loop = asyncio.get_event_loop() >>> loop2 = asyncio.get_event_loop() >>> loop is loop2 True # 两个loop实例是彻底相同的
这意味着在一个coroutine内部获取loop,也能够经过asyncio.get_event_loop()
来获得,并不须要将loop做为参数传递给协程函数。对于框架设计者来讲状况又不一样了,最好在函数设计中接受一个loop参数,以防止用户使用loop策略来作一些额外的事情。框架
注意
get_event_loop()
方法仅在一样的线程中生效,若是在一个新线程中,应该用new_event_loop()
来获取新的loop,并经过set_event_loop(loop)
来将其设为该线程下的loop。socket
若是在一个coroutine函数中建立tasks而不await它们,会发生什么?事实上它们将独立于这个coroutine函数内的执行上下文来运行,这个coroutine函数将会在它启动的任务完成以前退出。async
async def f(): loop = asyncio.get_event_loop() for i in range(5): loop.create_task(<coro>)
像上述状况,有时会在代码中看到loop变量,而后create_task()
才能被调用,另外一种解决方案是使用asyncio.ensure_future()
方法,这个方法不须要经过loop来调用。函数
async def f(): for i in range(5): asyncio.ensure_future(<coro>)
或能够经过辅助函数来作到。oop
def create_task(coro): return asyncio.get_event_loop().create_task(coro) async def f(): for i in range(5): create_task(<coro>)
loop.create_task()
和asyncio.ensure_future()
对初学者来讲是很微妙和困惑的,下一章讨论其中的差别。测试