asyncio
- 这里主要是介绍一下python中的协程,以及梳理一下在学习中的一些困惑,目前还没有在源码中进行验证,只记录自己的一些看法,如果和各位想法有出入,可以一起讨论
困惑
- 在写之前默认大家都应该大体清楚了一些协程的基本概念
- 首先我们先来看一个例子: 这个例子基本的流程是创建三个任务,进行并发操作,其中task作为任务,doing 作为任务中的模拟耗时
import asyncio
async def doing(name):
print(f"{name} task doing ...")
for i in range(100):
# print(f"{name}-{i} doing ...")
await asyncio.sleep(0.01)
async def task(name):
print(f"{name} task start ...")
await doing(name)
print(f"{name} task stop ...")
def main():
loop = asyncio.get_event_loop()
tasks = [
loop.create_task(task(name)) for name in range(3)
]
loop.run_until_complete(asyncio.wait(tasks))
if __name__ == "__main__":
main()
- result
0 task start ...
0 task doing ...
1 task start ...
1 task doing ...
2 task start ...
2 task doing ...
0 task stop ...
1 task stop ...
2 task stop ...
- 在网上很多例子中都是用asyncio.sleep(1)来模拟任务中的耗时任务,貌似还没有人来真正的自己写耗时任务,文档上也是强调asyncio.sleep(1)是一个协程,所以按照我的理解 await 作用应该是挂起当前task,释放CPU资源,将资源让给其他的任务,预设结果应该可能为
0 task start ...
1 task start ...
2 task start ...
···
- 但是结果却不是设想结果,也就是说明await 只是挂起了当前task,并且执行了doing的内容,之后我又做了一个实验,解除 == print(f"{name}-{i} doing …") == 注释,结果为:
···
0-57 doing ...
1-57 doing ...
2-57 doing ...
0-58 doing ...
1-58 doing ...
2-58 doing ...
···
- 这个结果表明三个任务在做并发,在来做一个实验,将doing中==await asyncio.sleep(0.01)==注释,循环设为3,结果为
0 task doing ...
0-0 doing ...
0-1 doing ...
0-2 doing ...
0 task stop ...
1 task start ...
1 task doing ...
1-0 doing ...
1-1 doing ...
1-2 doing ...
1 task stop ...
2 task start ...
2 task doing ...
2-0 doing ...
2-1 doing ...
2-2 doing ...
2 task stop ...
我们发现完全变成了同步方式,接下来我们引入如下问题
1. asyncio.sleep(1) 到底是什么
- 首先sleep确实是一个协程,从其他博客上知道它内部是一个定时器,他是一个 == 异步函数 == 而不是同步函数,来模拟异步耗时任务,为什么我们自己写的协程doing无法实现这个功能,因为我们的doing还是一个同步的代码,无法实现异步操作,就像如果我们使用异步爬虫,如下,其实我们看到结果后应该还是同步,因为requests是同步库,不支持异步操作,可以使用aiohttp来实现真正的异步操作,现在我们只是从现象来看本质,在我研究一下源码再来剖析我们的设想是否真的正确
# 将doing 换成
async def call_on():
status = requests.get('https://www.baidu.com')
return status
2. await 作用是什么
- 挂起当前协程