编程学习网 > 编程语言 > Python > Python教程—Python中如何使用async方式实现异步并发?
2023
12-04

Python教程—Python中如何使用async方式实现异步并发?

async方式实现异步并发,以下讲解的使用方式仅支持python3.7及以上版本,每个版本均更新了异步的不同的使用方法,大家感兴趣的可以去了解下。

所谓异步,就是程序执行一个协程任务,遇到协程任务需要等待的,且等待无需占用程序资源,程序可以继续执行其他的代码情况下,无需等待协程任务执行完毕,程序可挂起该协程任务,继续执行下一个协程任务,待被挂起的任务等待时间到,则程序返回继续执行该任务。
什么是协程呢?这里大家通俗理解成线程中的代码片段吧。这里就不展开解释,接下来主要讲async/await的理解及如何简单使用。
以下是自己的简单整理的思路,只是简单入门下如何使用,并未深入,如有错误,欢迎指正。如果想要深入学习,推荐带大家看这篇文章,异步编程的前因后果都讲的非常清楚。
深入理解Python异步编程(上) (qq.com)

安装
pip install asyncio

用法
关键字async关键字声明执行的函数是协程块

使用async关键字封装函数有何用呢?如果不封装是否有何影响?
通常函数的执行是,从头执行到尾,遇到return就退出。使用async关键字声明的函数,则会返回一个协程对象,在await关键字声明处中断,暂时挂起,去执行其他的函数,后续再返回继续执行。这里只是使用关键字async定义协程,函数单独执行的话,内部的内容并不会执行,而是返回协程对象,函数的运行还是需要借助事件循环去执行。
await关键字需要在哪些地方使用呢?  
     await关键字只能在async关键字修饰的函数内使用。  语法:await声明可等待对象  这里的对象只能是异步的程序或者是有__await__属性的对象。  表示对象主动让出执行权,暂时挂起,这里的对象是协程,表示协程暂时挂起,等待返回结果。

async def func():
  # 声明程序可以让出执行权的地方,也就是无需占用资源一直等待的地方
  await asyncio.sleep(等待时间)
创建事件循环,封装函数为协程任务,协程将会被自动调度
通过asyncio.create_task()创建协程任务,返回协程对象,同时create_task方法会将协程对象注册到事件循环中,通过loop异步调用协程对象运行,保存协程运行状态,方便获取每个协程的执行结果
执行协程任务对象时,遇到await则挂起协程任务,从而执行下一个协程任务
async def main():
  tasks = [
  asyncio.create_task(func),
  aysncio.creat_task(func),
  ...]
  await asyncio.wait(tasks)
通过run执行协程任务
run函数会监听main函数,直到main函数执行完毕后,才会结束事件循环
# 该方式在python3.7及以上版本才可使用
asyncio.run(main())

例子
例子共执行2个任务,任务1执行等待时间需要1s,任务2执行等待时间需要2s,按顺序执行共等待3s,异步执行则需要2s。
import time
import asyncio

# async声明函数say_after为协程对象
async def say_after(delay, what,name):
    # 步骤5:还未遇到await关键字,则正常执行任务1的代码
    # 步骤7:还未遇到await关键字,则正常执行任务2的代码
    print(f"开始执行{name}不让出执行权的代码")
    print(f"这是{name}正常执行的代码")
    # 步骤6:遇到await关键字,则表示任务1让出执行权,继续执行下一个协程任务对象任务2
    #       直到协程任务1对象的等待时间1s到了,再返回继续执行任务1
    # 步骤8:遇到await关键字,则表示任务2让出执行权,继续执行下一个协程任务对象
    await asyncio.sleep(delay)
    # 步骤9:由于这里只有2个协程任务对象,没有下一个,协程任务1等待的1s时间到
    #       执行协程任务1等待时间到了后面需要执行的代码,同时协程任务2的等待时间也过去了1s
    # 步骤10:协程任务2等待的2s时间到,开始执行后面的代码
    print(f"{name}执行时间:{time.strftime('%X')}")
    print(f"这是协程任务等待时间到了后需要执行的代码:{what}")

async def main():
    # 步骤2:2.1 创建协程任务task1,task2,此时已同步将协程任务注册到事件循环中,返回协程可执行任务,等待执行
    #       2.2 task1,task2协程函数调用后并不会执行函数内部
    #       2.3 此时每个任务的状态是pending,准备状态还未被执行
    for i in range(2):
        tasks = asyncio.create_task(
            say_after(i+1, f'内容{i+1}',name=f"任务{i+1}"))

    # 步骤3:打印开始执行时间
    print(f"所有协程任务开始执行前的时间:{time.strftime('%X')}")

    # 步骤4:声明tasks是可等待对象,执行协程任务
    await tasks

    # 步骤11:打印执行结束时间,最终执行结束即开始执行时间+最大的协程任务等待时间
    #        也就是task2协程任务的等待时间2s
    # 步骤12:结束执行时间
    print(f"所有协程任务最后执行前的时间:{time.strftime('%X')}")


# 步骤1:执行协程调度函数
asyncio.run(main())


aiohttp

aiohttp简介
若是想要实现并发http请求,那么就需要来认识下aiohttp。
aiohttp是asyncio和Python的异步HTTP客户端/服务器,aiohttp可以实现单线程并发IO操作。这里我们主要讲客户端发送请求的使用,服务端暂时不讲。

用法

创建session对象
通过aiohttp.ClientSession()创建一个客户端会话session

async with aiohttp.ClientSession() as session:
.....
使用session对象请求网页

async with aiohttp.ClientSession() as session:
  # session.get可修改为对应的请求方式,并添加对应的参数,如post请求,添加data的参数
   async with session.get('请求url') as resp:
        ........
关键字async关封装执行的函数

async def func():
      async with aiohttp.ClientSession() as session:
          async with session.get('请求url') as resp:
            .....
      await session.close()
主函数创建任务,协程调度执行任务

async def main():
  for i in range(并发次数):
    task = asyncio.create_task(func())
    
  await task
  ....
执行主函数

asyncio.run(main())

例子

例子共并发2个请求百度的任务,每个任务等待2s,顺序执行则需要4s,采用异步的方式,最终的执行时间仅需要2s。
import time
import asyncio
import aiohttp
import json


# async声明函数say_after为协程对象
async def get_https():
    async with aiohttp.ClientSession() as session:
        async with session.get(https://www.baidu.com) as resp:
            # 假设这里有请求网页后等待响应的时间
            await asyncio.sleep(2)
            print(resp.status)
    await session.close()


async def main():
    for i in range(2):
        tasks = asyncio.create_task(get_https())

    print(f"所有协程任务开始执行前的时间:{time.strftime('%X')}")
    await tasks
    print(f"所有协程任务最后执行前的时间:{time.strftime('%X')}")

asyncio.run(main())

以上就是Python教程—Python中如何使用async方式实现异步并发?的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取