温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Python中怎么利用Asyncio实现异步编程

发布时间:2021-07-10 15:59:12 来源:亿速云 阅读:118 作者:Leah 栏目:编程语言

本篇文章为大家展示了Python中怎么利用Asyncio实现异步编程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

异步是怎么一回事?

在传统的顺序编程中, 所有发送给解释器的指令会一条条被执行。此类代码的输出容易显现和预测。 但是…

譬如说你有一个脚本向3个不同服务器请求数据。  有时,谁知什么原因,发送给其中一个服务器的请求可能意外地执行了很长时间。想象一下从第二个服务器获取数据用了10秒钟。在你等待的时候,整个脚本实际上什么也没干。如果你可以写一个脚本可以不去等待第二个请求而是仅仅跳过它,然后开始执行第三个请求,然后回到第二个请求,执行之前离开的位置会怎么样呢。就是这样。你通过切换任务最小化了空转时间。尽管如此,当你需要一个几乎没有I/O的简单脚本时,你不想用异步代码。

还有一件重要的事情要提,所有代码在一个线程中运行。所以如果你想让程序的一部分在后台执行同时干一些其他事情,那是不可能的。

准备开始

这是 asyncio 主概念最基本的定义:

  • 协程 — 消费数据的生成器,但是不生成数据。Python 2.5 介绍了一种新的语法让发送数据到生成器成为可能。我推荐查阅David Beazley “A  Curious Course on Coroutines and Concurrency” 关于协程的详细介绍。

  • 任务 — 协程调度器。如果你观察下面的代码,你会发现它只是让 event_loop 尽快调用它的_step ,同时 _step  只是调用协程的下一步。

class Task(futures.Future):        def __init__(self, coro, loop=None):          super().__init__(loop=loop)          ...          self._loop.call_soon(self._step)         def _step(self):              ...          try:              ...              result = next(self._coro)          except StopIteration as exc:              self.set_result(exc.value)          except BaseException as exc:              self.set_exception(exc)              raise          else:              ...              self._loop.call_soon(self._step)
  • 事件循环 — 把它想成 asyncio 的中心执行器。

现在我们看一下所有这些如何融为一体。正如我之前提到的,异步代码在一个线程中运行。

Python中怎么利用Asyncio实现异步编程

从上图可知:

1.消息循环是在线程中执行

2.从队列中取得任务

3.每个任务在协程中执行下一步动作

4.如果在一个协程中调用另一个协程(await  <coroutine_name>),会触发上下文切换,挂起当前协程,并保存现场环境(变量,状态),然后载入被调用协程

5.如果协程的执行到阻塞部分(阻塞I/O,Sleep),当前协程会挂起,并将控制权返回到线程的消息循环中,然后消息循环继续从队列中执行下一个任务...以此类推

6.队列中的所有任务执行完毕后,消息循环返回***个任务

异步和同步的代码对比

现在我们实际验证异步模式的切实有效,我会比较两段 python 脚本,这两个脚本除了sleep 方法外,其余部分完全相同。在***个脚本里,我会用标准的  time.sleep 方法,在第二个脚本里使用 asyncio.sleep 的异步方法。

这里使用 Sleep 是因为它是一个用来展示异步方法如何操作 I/O 的最简单办法。

使用同步 sleep 方法的代码:

import asyncio    import time    from datetime import datetime        async def custom_sleep():        print('SLEEP', datetime.now())      time.sleep(1)     async def factorial(name, number):        f = 1      for i in range(2, number+1):          print('Task {}: Compute factorial({})'.format(name, i))          await custom_sleep()          f *= i      print('Task {}: factorial({}) is {}\n'.format(name, number, f))        start = time.time()    loop = asyncio.get_event_loop()     tasks = [        asyncio.ensure_future(factorial("A", 3)),      asyncio.ensure_future(factorial("B", 4)),  ]  loop.run_until_complete(asyncio.wait(tasks))    loop.close()     end = time.time()    print("Total time: {}".format(end - start))

脚本输出:

Task A: Compute factorial(2)    SLEEP 2017-04-06 13:39:56.207479    Task A: Compute factorial(3)    SLEEP 2017-04-06 13:39:57.210128    Task A: factorial(3) is 6     Task B: Compute factorial(2)    SLEEP 2017-04-06 13:39:58.210778    Task B: Compute factorial(3)    SLEEP 2017-04-06 13:39:59.212510    Task B: Compute factorial(4)    SLEEP 2017-04-06 13:40:00.217308    Task B: factorial(4) is 24     Total time: 5.016386032104492

使用异步 Sleep 的代码:

import asyncio    import time    from datetime import datetime        async def custom_sleep():        print('SLEEP {}\n'.format(datetime.now()))      await asyncio.sleep(1)     async def factorial(name, number):        f = 1      for i in range(2, number+1):          print('Task {}: Compute factorial({})'.format(name, i))          await custom_sleep()          f *= i      print('Task {}: factorial({}) is {}\n'.format(name, number, f))        start = time.time()    loop = asyncio.get_event_loop()     tasks = [        asyncio.ensure_future(factorial("A", 3)),      asyncio.ensure_future(factorial("B", 4)),  ]  loop.run_until_complete(asyncio.wait(tasks))    loop.close()     end = time.time()    print("Total time: {}".format(end - start))

脚本输出:

Task A: Compute factorial(2)    SLEEP 2017-04-06 13:44:40.648665     Task B: Compute factorial(2)    SLEEP 2017-04-06 13:44:40.648859     Task A: Compute factorial(3)    SLEEP 2017-04-06 13:44:41.649564     Task B: Compute factorial(3)    SLEEP 2017-04-06 13:44:41.649943     Task A: factorial(3) is 6     Task B: Compute factorial(4)    SLEEP 2017-04-06 13:44:42.651755     Task B: factorial(4) is 24     Total time: 3.008226156234741

上述内容就是Python中怎么利用Asyncio实现异步编程,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI