如果你想了解异步编程, 那么必然会涉及出许多相关概念.
堵塞 / 非堵塞
同步 / 异步
多进程 / 多线程 / 协程
为什么我要学习这个话, 因为我想搞懂异步框架和异步接口的调用. 所以, 我的学习路线是这样的:
1.python 异步编程
2.python web 异步框架 (tornado/sanic)
3. 异步接口调用 (aiohttp/httpx)
那么异步编程有什么好处? 在某些场景下它可以提高性能. 我们知道 CPU 的速度快于磁盘, 网络等 IO. 一旦遇到 IO 操作, 如读写文件, 发送网络数据时, 就需要等待 IO 操作完成, 才能进行下一步操作. 这种情况称为同步 IO. 我们可以使用多线程来解决这类问题, 另一种方式是通过异步.
python 在 3.4 版本引入 asyncio, 到 3.5 版本又加入 async/await 来简化异步的使用.
先来举个简单的例子, 假如, 你和女朋友逛街. 你的目的是去看新上市的华为 P40 手机, 而你女朋友是去看新款的衣服. 你们的逛街流程是这样的.
- import time
- def clothes_shop():
- print("女朋友看衣服..")
- time.sleep(8)
- print("... 出来了")
- def huawei_shop():
- print("体验手机..")
- time.sleep(5)
- print("... 出来了")
- print(time.ctime(), "开始逛街")
- clothes_shop()
- huawei_shop()
- print(time.ctime(), "结束.")
运行结果:
Thu Apr 16 00:08:22 2020 开始逛街
女朋友看衣服..
... 出来了
体验手机..
... 出来了
Thu Apr 16 00:08:35 2020 结束.
假设单位是分钟, 你们总共耗时 13 分钟.
接下来, 看看用异步是如何处理的:
- import asyncio
- import time
- async def shop(delay, what):
- print(what)
- await asyncio.sleep(delay)
- print("... 出来了")
- async def main():
- task1 = asyncio.create_task(shop(8, '女朋友看衣服..'))
- task2 = asyncio.create_task(shop(5, '体验手机..'))
- print(time.ctime(), "开始逛街")
- await task1
- await task2
- print(time.ctime(), "结束.")
- asyncio.run(main())
通过 async/await 语法进行声明, 是编写 asyncio 应用的推荐方式.
async 声明一个函数为异步函数.
await 声明处理比较耗费时的动作.
asyncio.run() 函数用来运行最高层级的入口点 main() 函数.
asyncio.create_task() 函数用来并发运行作为 asyncio 任务 的多个协程.
其实, 思路非常简单, 就是你和女朋友各逛各自的, 先出来的等等对方.
严重警告! 提醒广大直男, 现实生活中千万不要这么思考问题. 一定要陪女朋友一起看衣服, 还要主动去付钱.
来看看运行结果:
Thu Apr 16 00:19:19 2020 开始逛街
女朋友看衣服..
体验手机..
... 出来了
... 出来了
Thu Apr 16 00:19:27 2020 结束.
假设单位是分钟, 只需要 8 分钟搞定.
通过上面的例子, 可以看到 task1,task2 仍然有前后顺序, 这种前后顺序的时间可以忽略不计. 但是, 我们也是可以使用 asyncio.gather() 方法并发运行任务.
- #......
- async def main():
- print(time.ctime(), "开始逛街")
- await asyncio.gather(
- shop(8, '女朋友看衣服..'),
- shop(5, '体验手机..')
- )
- print(time.ctime(), "结束.")
- asyncio.run(main())
运行结果同上, 这里就不再贴了.
参考:
来源: https://www.cnblogs.com/fnng/p/12757395.html