python 异步操作async和await

1、协程Coroutine

协程(Co-routine),也可称为微线程,或非抢占式的多任务子例程,一种用户态的上下文切换技术(通过一个线程实现代码块间的相互切换执行)。在一个线程(协程)中,遇到io等待时间,线程可以利用这个等待时间去做其他事情。

2、async/await

async和await是针对asyncio提供的@asyncio.coroutine的新语法。

2.1、async

携程函数:python3.5之后使用 async def 函数名,定义的函数就叫携程函数。

携程对象:执行携程函数 函数名(),得到的就是携程对象。

注:执行协程函数得到协程对象,函数内部代码不会执行

# python 源码
>>> import asyncio

>>> async def main():
...     print('hello')
...     await asyncio.sleep(1)
...     print('world')

>>> main()
<coroutine object main at 0x1053bb7c8>

>>> asyncio.run(main()) # 执行协程函数内部代码,必须把协程对象交给事件循环处理
hello
world

其中,

asyncio.run(main()) 
等价于:
oop = asyncio.get_event_loop()
loop.run_until_complate(main())

2.2、await

await + 可等待对象(协程对象,Future,Task对象(IO等待))。

等待到对象的返回结果,才会继续执行后续代码。

import asyncio
import time

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

async def main():
    print(f"started at {time.strftime('%X')}")

    await say_after(1, 'hello')
    #await say_after(1, 'hello')执行完之后,才继续向下执行
    await say_after(2, 'world')

    print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

输出:

started at 17:13:52
hello
world
finished at 17:13:55

3、asyncio

asyncio 模块最大特点就是,只存在一个线程。由于只有一个线程,就不可能多个任务同时运行。asyncio是"多任务合作"模式(cooperative multitasking),允许异步任务交出执行权给其他任务,等到其他任务完成,再收回执行权继续往下执行。

asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。

3.1、asyncio事件循环(python3.6)

事件循环:去检索一个任务列表的所有任务,并执行所有未执行任务,直至所有任务执行完成。

执行协程函数,必须使用事件循环。

import asyncio

async def func1():
    print('协程1')

async def func2():
    print('协程2')

# task可为列表,即任务列表
# task = func1()
task = [func1(), func2()]
# 创建事件循环
loop = asyncio.get_event_loop()
# 添加任务,直至所有任务执行完成
loop.run_until_complete(asyncio.wait(task))
#关闭事件循环
loop.close()
# 事件循环关闭后,再次调用loop,将不会再次执行。

3.2、asyncio事件循环(python3.7)

python3.7省略的手动创建事件循环,可直接用asyncio.run()去执行协程任务。

import asyncio

async def func1():
    print('协程1')

async def func2():
    print('协程2')

task = [func1(), func2()]
# python3.7引入的新特性,不用手动创建事件循环
asyncio.run(task)

3.3、asyncio.create_task()

asyncio.create_task() 作为异步并发运行协程的函数Tasks。

将协程添加到asyncio.create_task()中,则该协程将很快的自动计划运行。

import asyncio

async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)
    
async def main():
    task1 = asyncio.create_task(
        say_after(1, 'hello'))

    task2 = asyncio.create_task(
        say_after(2, 'world'))

    print(f"started at {time.strftime('%X')}")

    # 两个任务同时执行,直到到所有任务执行完成。
    await task1
    await task2

    print(f"finished at {time.strftime('%X')}")

输出:

started at 17:14:32
hello
world
finished at 17:14:34

注:比不使用asyncio.create_task()的结果快了一秒,也即两个任务同时执行了。

3.4、asyncio.futures对象

官方文档对Future的介绍大致如下:

Future是特殊的低级等待对象,代表异步操作的最终结果。当等待Future对象时,它意味着协程将等待,直到在其他地方解析Future。需要在asyncio中使用将来的对象,以允许将基于回调的代码与async / await一起使用。通常,不需要在应用程序级别的代码中创建Future对象。(感觉有点类似于JS中的Promise)

使用async/await时 会自动创建Future对象。

3.5、asyncio.wait()

携程对象并行执行,使用asyncio.wait()同步。

task = [task1, task2]
asyncio.run(asyncio.wait(task))

4、应用实例

使用协程下载网页。

import asyncio
import requests
import time


async def result(url):
    res = await request_url(url)
    print(url, res)


async def request_url(url):
    res = requests.get(url)
    print(url)
    await asyncio.sleep(2)
    print("execute_time:", time.time() - start)
    return res


url_list = ["https://www.csdn.net/",
            "https://blog.csdn.net/qq_43380180/article/details/111573642",
            "https://www.baidu.com/",
            ]

start = time.time()
print(f"start_time:{start}\n")

task = [result(url) for url in url_list]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))

endtime = time.time() - start
print("\nendtime:", time.time())
print("all_execute_time:", endtime)

使用协程时,需要其底层方法实现时就是协程,才会生效,否则协程不生效!

此处使用的requests底层实现并不是异步,因此使用了time.sleep() 和 asyncio.sleep()模拟放大网络IO时间。

以下代码等价:

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))
等价于:
asyncio.run(asyncio.wait(task))

参考文章:

1、Python 异步 async/await(进阶详解)

https://blog.csdn.net/qq_43380180/article/details/111573642

2、python官方文档介绍(中文)

https://docs.python.org/zh-cn/3.7/library/asyncio-eventloop.html

3、Python异步编程 asyncio小白速通(bilibili视频)

https://www.bilibili.com/video/BV1dD4y127bD/

  • 9
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
异步编程是一种编程模式,它允许程序在等待某些操作完成时继续执行其他任务,而不是阻塞整个程序的执行。Python中的异步编程可以使用`async`和`await`关键字来实现。 `async`关键字用于定义一个异步函数,这个函数可以使用`await`关键字来挂起自身的执行,等待其他的异步操作完成后再继续执行。 下面是一个简单的例子,展示了如何使用`async`和`await`来实现异步编程: ```python import asyncio async def async_task(): print("异步任务开始") await asyncio.sleep(1) # 模拟耗时操作 print("异步任务结束") async def main(): print("主程序开始") await asyncio.gather(async_task(), async_task()) # 并发执行两个异步任务 print("主程序结束") asyncio.run(main()) ``` 在上面的例子中,我们定义了一个异步函数`async_task()`,它会打印一些信息,然后使用`await asyncio.sleep(1)`来模拟一个耗时操作。然后我们定义了另一个异步函数`main()`,它会并发地执行两个`async_task()`函数。最后,在`asyncio.run(main())`中运行主程序。 通过运行上面的代码,你会看到输出的顺序是"主程序开始" -> "异步任务开始" -> "异步任务开始" -> "异步任务结束" -> "异步任务结束" -> "主程序结束"。可以看到,在执行异步任务时,主程序不会被阻塞,而是继续执行其他任务。 异步编程在处理I/O密集型任务时特别有用,因为它可以充分利用等待I/O操作完成的时间,同时执行其他任务,提高程序的性能和响应性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

jingbo1801

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

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

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

打赏作者

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

抵扣说明:

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

余额充值