文章插图
2.1 定义协程协程就是一个函数,只是它满足以下几个特征:
- 依赖 I/O 操作(有 I/O 依赖的操作)
- 可以在进行 I/O 操作时暂停
- 无法直接运行
Python 协程属于可等待对象,因此可以在其他协程中被等待 。
什么叫可等待对象?——await,如果前面被标记 await 就表明他是个协程,我们需要等待它返回一个数据 。
文章插图
举个例子,我从网络上下载某个数据文件下载到我的本地电脑上,这很显然是一个 I/O 操作 。比方这个文件较大(2GB),可能需要耗时 30min 才能下载成功 。而在这 30min 里面,它会卡在 await 后面 。这个 await 标记了协程,那就意味着它可以被暂停,那既然该任务可以被暂停,我们就把它分离出去 。我这个线程继续执行其它任务,它这个 30min 分出去慢慢的传输,我这个程序再运行其他操作 。
上面的代码,Python 3.6 会给你报错 。报错信息如下:
文章插图
为什么会出现这样的报错呢?
因为从 Python 3.7+ 之后 Python 已经完全支持异步了,Python 3.6 之前只是支持部分异步,许多的方法是非常冗长的 。
一个异步函数调用另一个异步函数:
tips:
异步主要做得是 I/O 类型,CPU 密集型就不需要使用异步 。
一个异步调用另一个异步函数,不能直接被调用,必须添加 await
我们使用代码验证一下,不加 await 调用试一试:
文章插图
输出结果:
文章插图
我们添加上 await 即可正常运行:
文章插图
运行结果:
文章插图
运行成功并没有报错,接下来我们要输出得到的结果该怎么编写代码呢?直接赋值即可:
文章插图
Ps:async 标记异步,await 标记等待 。
如果我们不想使用 await 来运行异步函数,那这个时候我们就可以按如下方法来运行代码:
文章插图
首先我们来定义一个协程,体验一下它和普通进程在实现上的不同之处,代码如下:
文章插图
代码示例二中,我们首先引入了 asyncio这个包,这样我们才可以使用 async和 await,然后我们使用 async定义了一个 execute方法,方法接收一个数字参数,方法执行之后会打印这个数字 。
随后我们直接调用了这个方法,然而这个方法并没有执行,而是返回了一个 coroutine协程对象 。随后我们使用 get_event_loop方法创建了一个事件循环 loop,并调用了 loop对象的 run_until_complete方法将协程注册到事件循环 loop中,然后启动 。最后我们才看到了 execute方法打印了输出结果 。
可见,async定义的方法就会变成一个无法直接执行的 coroutine对象,必须将其注册到事件循环中才可以执行 。
上面我们还提到了 task,它是对 coroutine 对象的进一步封装,它里面相比 coroutine 对象多了运行状态,比如 running、finished 等,我们可以用这些状态来获取协程对象的执行情况 。
在上面的例子中,当我们将 coroutine 对象传递给 run_until_complete 方法的时候,实际上它进行了一个操作就是将 coroutine 封装成了 task 对象,我们也可以显式地进行声明,如下所示:
推荐阅读
- 看我怎么通过Python脚本给100台网络设备一键化下发相同的配置
- 无货源店铺现在还能做吗 无货源开店还能不能做
- 2020开网店还能行吗 2020年开网店咋样
- 教师|专业还会影响择偶?这几个专业择偶时不占优势,男同学要谨慎考虑
- 淘宝直通车推广怎么做 淘宝直通车精准推广还是广泛推广好
- 淘宝网店虚拟店还能开吗 淘宝虚拟产品开店教程
- 直通车智能计划点击率低 直通车标准好还是智能好
- 万圣节吃糖还是万圣夜吃糖
- 淘宝开店还有前景吗 现在开淘宝店前景怎么样
- 水培富贵竹,7个技巧能快速生根,还要注意4个方面,才能油绿旺盛