【Python】多任务异步协程

一、简单说说异步协程 

当我们在程序中用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))

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SamRol

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值