讲讲我在使用python异步IO语法时踩过的坑
简单介绍异步IO的原理
以及利用最新语法糖实现异步IO的步骤,
然后给出实现异步的不同例子
网上找了很多python的asyncio示例.很多都是用
# 获取EventLoop: loop = asyncio.get_event_loop() # 执行coroutine loop.run_until_complete(hello()) loop.close()
通过create_future向里面添加task的方法来进行异步IO调用.
asyncio.run() asyncio.create_task() asyncio.gather()
下面通过实例具体分析asyncio异步的原理和使用方法
async def foo(): print('----start foo') await asyncio.sleep(1) print('----end foo')/*预期想要的结果----start foo(等待一秒)----end foo*/
async是旧版本装饰器的语法糖
(异步环境是我自己创造的为了理解异步操作发明的词汇)
开启这个异步环境的标志是
asyncio.run(foo())
async def foo(): print('start foo') await asyncio.sleep(1) print('----end foo') if __name__ == '__main__': asyncio.run(foo())
执行以下之后发现结果没问题
def foo2(): print('----start foo') time.sleep(1) print('----end foo') def bar2(): print('----start bar') time.sleep(2) print('----end bar') if __name__ == '__main__': foo2() bar2() /* 预期输出: ----start foo (等待1秒) ----end foo ----start bar (等待2秒) ----end bar */
把上面的函数改写成异步之后
async def foo(): print('----start foo') await asyncio.sleep(1) print('----end foo') async def bar(): print('****start bar') await asyncio.sleep(2) print('****end bar') async def main(): await foo() await bar() if __name__ == '__main__': asyncio.run(main())
我们想要的结果是
----start foo
****start bar
(等待1秒)
----end foo
(等待1秒)
****end bar
----start foo
(等待1秒)
----end foo
****start bar
(等待2秒)
****end bar
这是为什么呢
那么如何一起执行呢
基本的有两种方法
1.采用函数gather
官方文档中的解释是
asyncio.
gather
(*awsloop=Nonereturn_exceptions=False)
并发aws可等待对象。
aws
aws
return_exceptionsFalse
gather()
aws不会被取消
return_exceptionsTrue
,异常会和成功的结果一样处理,并聚合至结果列表。
gather()
被取消被取消。
aws被取消CancelledError
gather()
不会
因此代码就有了
async def foo(): print('----start foo') await asyncio.sleep(1) print('----end foo') async def bar(): print('****start bar') await asyncio.sleep(2) print('****end bar') async def main(): res = await asyncio.gather(foo(), bar()) print(res) if __name__ == '__main__': asyncio.run(main())
asyncio.
create_task
(coro)
get_running_loop()
RuntimeError
。
在 Python 3.7 中被加入asyncio.ensure_future()
async def foo(): print('----start foo') await asyncio.sleep(1) print('----end foo') async def bar(): print('****start bar') await asyncio.sleep(2) print('****end bar') async def main(): asyncio.create_task(foo()) asyncio.create_task(bar()) if __name__ == '__main__': asyncio.run(main())
----start foo
****start bar
因此需要等待它们执行完毕.
最后的代码为
async def foo(): print('----start foo') await asyncio.sleep(1) print('----end foo') async def bar(): print('****start bar') await asyncio.sleep(2) print('****end bar') async def main(): task1 = asyncio.create_task(foo()) task2 = asyncio.create_task(bar()) await task1 await task2 if __name__ == '__main__': asyncio.run(main())
如果有多个请求
async def foo(): print('----start foo') await asyncio.sleep(1) print('----end foo') async def main(): tasks = [] for i in range(10): tasks.append(asyncio.create_task(foo())) await asyncio.wait(tasks) if __name__ == '__main__': asyncio.run(main())
async def foo(): print('----start foo') await asyncio.sleep(1) print('----end foo') async def bar(): print('****start bar') await asyncio.sleep(2) print('****end bar') async def main(): tasks = [] for i in range(10): tasks.append(asyncio.create_task(foo())) for j in range(10): tasks.append(asyncio.create_task(bar())) await asyncio.wait(tasks) if __name__ == '__main__': asyncio.run(main())
异步嵌套
async def foo(): print('----start foo') await asyncio.sleep(1) print('----end foo') async def bar(): print('****start bar') await asyncio.sleep(2) print('****end bar') async def foos(): print('----------------------') tasks = [] for i in range(3): tasks.append(asyncio.create_task(foo())) await asyncio.wait(tasks) async def main(): tasks = [] for i in range(3): tasks.append(asyncio.create_task(foos())) for j in range(3): tasks.append(asyncio.create_task(bar())) await asyncio.wait(tasks) if __name__ == '__main__': asyncio.run(main())
async def foo(): print('----start foo') await asyncio.sleep(1) print('----end foo') async def foos(): print('----------------------') tasks = [] await foo() await foo() await foo() async def main(): tasks = [] for i in range(3): tasks.append(asyncio.create_task(foos())) await asyncio.wait(tasks) if __name__ == '__main__': asyncio.run(main())