【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)

相关推荐
维克兜率天12 小时前
【维克】弹性策略:用“乖离率“捕捉超跌反弹
android·开发语言·python·深度学习·kotlin·量化
SamChan9012 小时前
PDF页面旋转与CropBox陷阱:译文回填位置总是错位的根因实测
python·ai·pdf·wpf
程序员清风12 小时前
Java 智能体开发:从对话接口到任务执行
java·人工智能·python
2601_9669496512 小时前
每日自动更新股票行情:如何设计可靠的数据任务,避免重复写入和脏数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
打工仔折腾 AI12 小时前
从零写一个CAD 02:实体容器、Esc取消与键盘失灵的排查
人工智能·后端·python·性能优化
用户83562907805112 小时前
使用 Python 拆分和提取 PDF 页面
后端·python
用户83562907805112 小时前
使用 Python 操作 PowerPoint 中的图片
后端·python
梅雅达编程笔记12 小时前
02_BeautifulSoup网页数据提取
开发语言·爬虫·python·beautifulsoup·数据采集
ai小陈13 小时前
深度学习CUDA OOM排查:显存占用与碎片问题实战
服务器·人工智能·python·深度学习·ai·gpu算力
小小张说故事13 小时前
pandas 读大 CSV 太慢?6 个实测提速技巧(dtype / 分块 / 引擎选择)
后端·python·pandas