【Python】 async/await

【Python】 async/await

1. 前言

最近在使用的PTB的API,里面会碰到Python协程的使用,记录个人对此的浅显理解。

2. 进程、线程、协程

  • 进程:由一个可执行程序以及该可执行程序执行过程中所需要的内存资源组成,每个进程有自己独立的内存管理,因此进程切换、通信需要消耗很大的资源。
  • 线程:组成同进程一样,但是所占用的资源相比进程更少;线程为进程中一段程序执行流。
  • 协程:微线程,所需的资源进一步减少。
  • 进程和线程关系:进程为操作系统分配资源的最小单位,一个进程由一个或多个线程组成,对于一个进程中的多个线程,他们共享操作系统给该进程所分配内存资源。

3. Pyhton中协程实现

用到的关键字为async/await,这两个关键字搭配使用。

async声明一个函数为异步函数,异步函数的特点是在函数执行过程中遇到await关键字则挂起,去执行其他异步函数。

await用于暂定异步函数的执行(并发操作中,把程序控制器交给主程序,让其分配其他协程执行),其后面只能跟async修饰的异步函数或带有__await__属性的对象。

python 复制代码
# This is a sample Python script.
import time
import asyncio


async def subtask(name,cost_time):
    await asyncio.sleep(cost_time)
    print('[{}] Current task is {}.'.format(time.time(), name))


async def task(name, cost_time):
    print('[{}] {} is starting.'.format(time.time(), name))
    time_start = time.time()
    await subtask(name, cost_time)
    time_end = time.time()
    print('[{}] {} is ending.'.format(time.time(), name, time_end - time_start))
    return '{} costs {}s'.format(name, time_end - time_start)


async def demo_1():
    print('[{}] Demo1 starts tasks ......'.format(time.time()))
    st = time.time()
    result1 = await task('Task 1', 3)
    result2 = await task('Task 2', 6)
    result3 = await task('Task 3', 2)
    et = time.time()
    print('\b----- result ----')
    print('Total task cost {}s.'.format(et - st))
    print(result1)
    print(result2)
    print(result3)
    print()


async def demo_2():
    print('[{}] Demo2 starts tasks ......'.format(time.time()))
    st = time.time()
    result = await asyncio.gather(
        task('Task 1', 3),
        task('Task 2', 6),
        task('Task 3', 2),
    )
    et = time.time()
    print('\b----- result ----')
    print('Total task cost {}s.'.format(et - st))
    for item in result:
        print(item)
    print()


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    asyncio.run(demo_1())
    asyncio.run(demo_2())

运行结果:

text 复制代码
[1709704883.4558887] Demo1 starts tasks ......
[1709704883.4558887] Task 1 is starting.
[1709704886.4710522] Current task is Task 1.
[1709704886.4710522] Task 1 is ending.
[1709704886.4710522] Task 2 is starting.
[1709704892.4716516] Current task is Task 2.
[1709704892.4716516] Task 2 is ending.
[1709704892.4716516] Task 3 is starting.
[1709704894.4731288] Current task is Task 3.
[1709704894.4731288] Task 3 is ending.
----- result ----
Total task cost 11.017240047454834s.
Task 1 costs 3.0151634216308594s
Task 2 costs 6.000599384307861s
Task 3 costs 2.0014772415161133s

[1709704894.475127] Demo2 starts tasks ......
[1709704894.475127] Task 1 is starting.
[1709704894.475127] Task 2 is starting.
[1709704894.475127] Task 3 is starting.
[1709704896.4786284] Current task is Task 3.
[1709704896.4786284] Task 3 is ending.
[1709704897.4788241] Current task is Task 1.
[1709704897.4788241] Task 1 is ending.
[1709704900.4797897] Current task is Task 2.
[1709704900.4797897] Task 2 is ending.
----- result ----
Total task cost 6.004662752151489s.
Task 1 costs 3.003697156906128s
Task 2 costs 6.004662752151489s
Task 3 costs 2.0035014152526855s

async声明的函数为一部函数,其需要在时间循环中调用,若向普通函数调用异步函数,未能体现其异步特征,如同Demo_1。asyncio.run()函数负责运行主体函数,并管理事件循环。asyncio.gather()可以并发多个异步函数。调用Demo_2,Task1、Task2、Task3同时执行,执行Task1的过程中遇到await则挂起Task1,去执行Task2,Task2遇到await则挂起,asyncio.gather()会在3个任务之间进行调度。

参考

1 理解Python协程(Coroutine)

相关推荐
前端精髓1 小时前
结构化输出with_structured_output(抽卡)
python·langchain
尹人入圣2 小时前
目前热门的IP驱动产业新场景新工具
网络·python·网络协议·tcp/ip
Nuanyt3 小时前
Agent 学习笔记(下篇三):上线工程、进阶选择与操作界面(Stage 7 / 7.5 / 8 + 延伸路线)
笔记·python·学习·memory·aiagent·harness
吴卫斌3 小时前
定投ETF实战指南(四):行业/主题ETF——定投的“进攻端“
开发语言·python·股票·量化
2601_967987373 小时前
Python——入门级(定义功能def函数)
python·函数·可变参数·默认参数·关键字参数
专注仿真6 小时前
梯度提升类(XFBoost)算法详解与代码实例
开发语言·人工智能·python·算法·大模型训练·控制算法
外收内放6 小时前
Python基础语法练习题(75)
开发语言·python·学习
黑十7 小时前
PyTorch 报 “no CUDA GPUs are available“ 怎么办?3 步排查
服务器·网络·人工智能·pytorch·python
threelab7 小时前
开源图片去水印代码
python
taller_20009 小时前
【012】数据类型入门: Excel 数据到 Python 值的转换
python·excel·pie·py