by 90后老和尚
建议学习路线:README-->交互式教学-->实战教学-->进阶教学-->trick to asynchronously import
def f(*args,**kwargs):
print("FUnction f")
class F():
def __call__(self):
print("FUnction f")
f=F()
f(*args,**kwargs)
async def g(*args,**kwargs):
print("Coroutine function g")
coroutine=g(*args,**kwargs)
上面的函数f是一个代码包,通过调用函数运行其内包含的代码。而协程函数g不是代码包,调用g(g(*args,**kwargs))并不会运行其定义体中的代码。通过type()函数可以查看f、g都是函数类。可以相信协程函数类是继承于函数类,其__call__()方法被重写了,不包含定义体中的代码,return一个协程对象:
coroutine=g(*args,**kwargs)
import asyncio
async def main():
#异步代码放置处
pass
asyncio.get_event_loop().run_until_complete(main())
import asyncio
async def main():
#异步代码放置处
pass
loop = asyncio.get_event_loop()
loop.create_task(main())
loop.run_forever()
至此,同步编程环境变成了同步兼异步编程环境。注意,在这里别把main协程函数的定义体当作一个协程函数内部,应该理解为异步版的Python语言(aiopython?),忘掉main外面的东西。下面之说main里面发生的事情。
async def main():
print("Hello world")
import requests
requests.get("http://www.baidu.com")
requests.get("http://www.baidu.com")
requests.get("http://www.baidu.com")
requests.get("http://www.baidu.com")
requests.get("http://www.baidu.com")
requests.get("http://www.baidu.com")
requests.get("http://www.baidu.com")
requests.get("http://www.baidu.com")
requests.get("http://www.baidu.com")
requests.get("http://www.baidu.com")
async def main():
async def coro():#协程函数的定义
print('Hello world')
return 123
coroutine=coro()#协程的生成
asyncio.create_task(coroutine)#协程的注册(遇到不兼容试试asyncio.ensure_future)
上面演示了一个协程函数的定义、协程的生成和协程的注册全过程。其中,协程的注册可以理解为这个协程独立运行,不会堵塞当前协程,不会占用当前协程的时间。这是最基础的用法,协程的注册这一步是注册协程之后三不管的:
async def main():
async def coro():#协程函数的定义
print('Hello world')
return 123
coroutine=coro()#协程的生成
task=asyncio.create_task(coroutine)#协程的注册
res=await task
await task#等待运行完
res=await task#等待协程完成,并且获取协程返回值
async def main():
async def coro():#协程函数的定义
print('Hello world')
return 123
coroutine=coro()#协程的生成
task1=asyncio.create_task(coroutine)#协程的注册
coroutine2=coro()#协程的生成
task2=asyncio.create_task(coroutine2)#协程的注册
coroutine3=coro()#协程的生成
task3=asyncio.create_task(coroutine3)#协程的注册
res1=await task1
res2=await task2
res3=await task3
async def main():
tasks=[]#搜集task的列表
for i in range(30):
tasks.append(asycnio.create_task(asyncio.sleep(i)))
#现在因为打印,需要用到结果
for task in tasks:
print(await task)
await asyncio.sleep(1)
的协程使用方式。在本教程中,这被解释为一种隐式写法,等同
await asyncio.create_task(asyncio.sleep(1))
async def main():
tasks = [] # 搜集task的列表
for i in range(3):
async def coro():
return i
tasks.append(asyncio.create_task(coro()))
#打印需要结果
for task in tasks:
print(await task)
2
2
2
0
1
2
async def main():
tasks = [] # 搜集task的列表
for i in range(3):
async def coro(i=i):#参数传值
return i
tasks.append(asyncio.create_task(coro()))
#打印需要结果
for task in tasks:
print(await task)
通过上面的讲解,不知道你有没有发现一个分形嵌套的现象:在协程内注册协程(内注册协程内注册协程......)。并发的概念已经解释不了这个现象了,协程并发是默认的情况,反而根据业务需求需要搞一些阻塞了(await)。结合业务的具体逻辑,不相关的部分拆分成不同协程,相关的部分包装成同一个协程控制先后;协程是从其他的协程生成,协程内部亦可继续生成新的协程;协程由事件循环调度,所有协程地位平等地在并发,没啥相干——协程能够等待的,只是task。
async def aio_get():
import aiohttp
async with aiohttp.ClientSession() as session:
async with session.get("http://www.baidu.com") as r:
res = await r.text()