1. Python协程 --- Async和Await的使用

文章介绍了Python线程的缺点,由于GIL全局解释器锁的存在,导致多线程无法实现真正的并行执行。为解决这一问题,文章提出了使用协程进行异步编程的概念,通过async和await关键字来定义和等待异步函数。示例展示了如何使用asyncio库创建和管理协程任务,以及如何通过Task和asyncio.gather()调度并发执行。通过对比异步和非异步执行的时间消耗,强调了异步执行的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 说明:

线程的缺点:在Python解释器中有一个GIL锁 — Global Interpreter Lock,在Python中的线程执行前都会获得这个GIL锁,每次执行100条字节码后,解释器就自动释放这个GIL锁,让别的线程有机会执行。Python会把所有的线程都加上这把锁,然后多线程之间只能交替执行,并未实现真正的并发执行。
使用协程可以避免,相当于异步编程
async关键字用于定义异步函数
await关键字用于等待异步函数执行(可等待对象包括:协程对象,Task对象,Future对象)

2. 简单使用:

# 引入协程包
import asyncio
import time

def demoAsync():
    # 使用async修饰普通函数,可将普通函数变成异步函数
    async def task1():
        print("Execute the first task...")
        # 耗时操作使用await修饰,这样会随机进入下一个协程函数执行
        await asyncio.sleep(3)
        print("the first task is done....")

    async def task2():
        print("Execute the second task...")
        await asyncio.sleep(3)
        print("the second task is done...")

    async def task3():
        print("Execute the third task...")
        await asyncio.sleep(3)
        print("the third task is done...")

    # 创建任务事件循环
    loop = asyncio.get_event_loop()
    # 将异步任务加入到一个列表中,形成任务列表
    tasks = [task1(), task2(), task3()]
    # 开始任务事件循环,直到最后一个任务执行结束
    loop.run_until_complete(asyncio.wait(tasks))
    # 最后一个任务执行结束后,关闭循环
    loop.close()


def demoNormal():
    def task1():
        print("Execute the first task...")
        # 耗时操作使用await修饰,这样会随机进入下一个协程函数执行
        time.sleep(3)
        print("the first task is done....")

    def task2():
        print("Execute the second task...")
        time.sleep(3)
        print("the second task is done...")

    def task3():
        print("Execute the third task...")
        time.sleep(3)
        print("the third task is done...")

    task1()
    task2()
    task3()


if __name__ == '__main__':
    startAsync = time.time()
    demoAsync()
    endAsync = time.time()
    # 用了异步执行,大概使用3s左右的时间  Async Time:3.0043070316314697
    print(str("Async Time:" + str(endAsync - startAsync)))

    startNormal = time.time()
    demoNormal()
    endNormal = time.time()
    # 不用异步,则打印出来的时间应该时9s左右  Normal time:9.009456157684326
    print(str("Normal time:" + str(endNormal - startNormal)))

3. Task对象:

Tasks用于并发调度协程,通过asyncio.create_task(协程对象)的方式创建Task对象,这样可以让协程加入事件循环中等待被调度执行,此函数一次只能添加一个协程任务到事件循环种,使用**asyncio.gather(协程对象1,协程对象2,…)**可以一次加入多个协程任务到事件循环种。
注意:asyncio.create_task() 函数在 Python 3.7 中被加入,本质上是将协程对象封装成task对象,并将协程立即加入事件循环,同时追踪协程的状态。

import asyncio


async def func():
    print(1)
    await asyncio.sleep(2)
    print(2)
    return "返回值"


async def main():
    print("main开始")

    # 创建协程,将协程函数加入到事件循环中,处于就绪状态,还未执行。
    task1 = asyncio.create_task(func())

    # 使用 gather 函数可以一次性将多个协程函数加入事件循环中。
    task2 = asyncio.gather(func(), func(), func())

    print("main结束")

    # 当执行某协程遇到IO操作时,会自动化切换执行其他任务。
    # 此处的await是等待相对应的协程全都执行完毕并获取结果
    ret1 = await task1  # task1 执行完之后,再执行下面的代码
    ret2 = await task2

    print(ret1, ret2)


asyncio.run(main())	# 使用run()方法启动协程任务执行,在python3.7的版本能够使用这种方式

持续更新中,请大家多多关注…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

山间点烟雨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值