一、简单说说异步协程
当我们在程序中用time()里的sleep函数时,往里面设置3秒的时间,程序就会等待3秒结束后才继续执行下面的代码,在等待过程中程序处于终断状态不执行任何代码。但是如果我们调用了异步协程的sleep,程序在等待的过程中会执行其他代码,从而节省代码运行的时间。
当我们的程序需要等待上一条代码执行完成才能执行下一行代码时,不妨用异步协程来减少代码的运行时间,这就是异步协程的大概的概念。下面我用代码举个例子。
二、代码举例
import time
def func1():
print("这是方法一")
time.sleep(3)
print("这是方法一")
def func2():
print("这是方法二")
time.sleep(3)
print("这是方法二")
def func3():
print("这是方法三")
time.sleep(3)
print("这是方法三")
t1 = time.time()
if __name__ == '__main__':
f1 = func1()
f2 = func2()
f3 = func3()
tasks = [
f1,f2,f3
]
t2 = time.time()
print(t2-t1)
运行时间大概是9秒:
正常的函数在执行时是不会中断的,所以你要写一个能够中断的函数,就需要添加async关键字变成一个特殊函数。
await 用来声明程序挂起。在特殊函数内部,凡是阻塞操作前都必须使用await进行修饰。比如异步程序执行到某一步时需要等待很长时间,就将此挂起,去执行其他的异步程序。await 后面只能跟异步程序或有__await__属性的对象。
import asyncio
import time
async def func1():
print("这是方法一")
await asyncio.sleep(3)
print("这是方法一")
async def func2():
print("这是方法二")
await asyncio.sleep(3)
print("这是方法二")
async def func3():
print("这是方法三")
await asyncio.sleep(3)
print("这是方法三")
if __name__ == '__main__':
f1 = func1()
f2 = func2()
f3 = func3()
tasks = [
f1,f2,f3
]
t1 = time.time()
#一次性启动多个任务(协程)
asyncio.run(asyncio.wait(tasks))
t2 = time.time()
print(t2-t1)
用异步协程运行时间大概3秒完成:
三、使用多任务异步协程具体步骤
1.创建协程对象
async def abc(): #协程函数
pass
c = abc() #这个就是协程对象
2.创建任务对象
task = asyncio.ensure_future(abc)
3.创建多任务列表
tasks = []
tasks.append(task)#把任务对象加进任务列表
4.创建事件循环对象
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
5.创建回调
async def get_request(url): #特殊函数
return page_text
#回调方法
def parse(t):
page_text = t.result()#result()可以拿到特殊函数的返回值
print(page_text)
task.add_done_callback(parse)#回调
小示例:
import asyncio
import requests #request不支持异步
import aiohttp
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36'
}
urls = [
'https://www.baidu.com/?tn=40020637_3_oem_dg',
'https://www.yooc.me/group/5717105/exam/255456/detail#question-38353286',
'https://www.python.org/'
]
async def get_request(url):
#实例化请求对象。这里用with的原因是,with会有文件管理层自动帮我们执行close函数
async with aiohttp.ClientSession() as session:
#调用get发起请求,返回一个响应对象
async with session.get(url=url,headers=headers) as response:
page_text = await response.text() #阻塞操作前加上await
return page_text
def parse(t): #回调特殊函数方法
page_text = t.result()
print(page_text)
if __name__ == '__main__':
tasks=[] #创建任务列表
for url in urls:
#创建协程对象
c = get_request(url)
#创建任务对象
task = asyncio.ensure_future(c)
#回调
task.add_done_callback(parse)
#把任务加进任务列表
tasks.append(task)
#创建事件循环对象
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))