热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python协程简介

Python协程简介什么是协程代码实现总结当我们要完成一个简单的任务的时候,我们通常就是按照事件的先后顺序按照过程编程,同头到尾程序逐行执行࿰

Python 协程简介

  • 什么是协程
  • 代码实现
  • 总结



当我们要完成一个简单的任务的时候,我们通常就是按照事件的先后顺序按照过程编程,同头到尾程序逐行执行,当我们需要实现的功能越复杂对性能要求越高时我们开始慢慢引入了多线程、多进程、协程等概念,多线程和多进程这个比较好理解,但是协程可能平时就见的不多了,本文对Python 协程到底是什么做出简介。以下全是个人理解如有不妥请多多指正。
什么是协程

根据维基百科给出的定义,“协程 是为非抢占式多任务产生子程序的计算机程序组件,协程允许不同入口点在不同位置暂停或开始执行程序”。听上去感觉很难懂,这里举上一个小小的例子,多线程和多进程都是可以理解为有多个CPU在确实的运行相应的程序,程序并没有发生中断,而协程是运行发生中断的,何时发生中断是由用户决定,产生中断后当前的函数停止工作转而去执行另外一个函数,这个对于嵌入式的中断有点这种意思,单片机当中现在正在运行main函数,这个时候外部中断触发了,main暂时停止转而去执行中断函数,这个时候可能会出现一个想法这不在函数里面调用另外一个函数也是实现的相同功能吗,注意这只是说协程表现出来的一种形式,协程是协调个部分代码达到资源最大利用,这才是真正的协程,在协程中要有任务的安排调整
讲个故事可能来的比较快一点,现在我们要做的一件事那就是安装Ubuntu系统,之前通过问别人我们大概知道了操作流程是先下载镜像文件,然后在进制作启动盘然后吧啦吧啦一系列操作,好现在我们就用一个单线程的人来模拟这个过程,首先我们进入一个操作也就是程序的一个函数,我们先下载镜像,先打开网站之后一顿操作过后就显示下载进度条了,注意这个动作(想象成程序的函数)还没有执行完,因为我们还没有下载完整个镜像,这个时候我们就开始等进度条,一秒过去了没下载完,我们再等等,两秒过去了还没下载完,这个时候我们就开始不耐烦了,我看进度条显示下载还剩余10分钟,我们好像可以干点别的事情,等下载完过后再来操作,我们这个时候就不再等待了下载了,转而去网站上看等会下载完成了怎么制作启动盘,这个时候我们就实现了任务的调度,从下载镜像转到了流量网页。协程就是这样发生在一个可能发生长时间阻塞的地方,我们不是让CPU做无用的等待,而是让CPU在等待的时间干点其他有用的事情,我们手动进行任务切换的过程就是协程。

代码实现

Python的协程经历了很长的发展,由于只是简介,只介绍最常用也是最简单的一种用法
我们编写一个程序模拟刚才的过程
首先采用最我们用延迟模拟这个过程的耗时,最后统计总的耗时时间

import time def download_ubuntu():time.sleep(5)# 查阅相关操作的教程
def look_up_how_to_operate():time.sleep(3)def install_ubuntu():download_ubuntu()look_up_how_to_operate()def main():start = time.time()install_ubuntu()end = time.time()print ('Cost {} seconds'.format(end - start))if __name__ == "__main__":main()

运行这段代码,我们得到下面的运行时间,无疑就是各个操作时间的累加

Cost 8.004846334457397 seconds

下面我们开始优化过程

import asyncio
import time # 用async表示这个是一个异步的函数表示这个函数是可发生中断的
async def download_ubuntu():# await后面需要解释一个可等待的对象,可以等待对象可以理解为async声明的函数或者具有__await__ 属性的对象,这个时候保存函数的状态跳出函数转而去执行其他的操作await asyncio.sleep(5)async def look_up_how_to_operate():await asyncio.sleep(3)def install_ubuntu():# 创建一个事件循环进而实现任务的调度loop = asyncio.get_event_loop()tasks = [download_ubuntu(),look_up_how_to_operate()]loop.run_until_complete(asyncio.wait(tasks))loop.close()def main():start = time.time()install_ubuntu()end = time.time()print ('Cost {} seconds'.format(end - start))if __name__ == "__main__":main()

通过计时我们看到时间明显就缩短了,将其中的3s就优化出来了,是不是很神奇。

Cost 5.0030436515808105 seconds

应该是在Python 3.5之后提出了这种新的async/await的操作,在以前的操作中协程还是很麻烦的,但是这种提供了很方便的操作,这个例子或许不是特别的合适下一篇博客会在ROS的实践中继续讲解协程。在本文末尾会对代码做出简要的讲解。

总结

总结起来协程就是实现用户自己编写代码级别的任务的调度。发生在我们需要调用其它模块的函数,这个函数是请求其他模块的一个函数,我们对本线程的任务做出相应的调整。
将一个函数声明为async就表示这个函数是一个可以被中断的异步函数,在产生中断过后去执行其他的函数。await关键字表示等待这个步骤完成,这个关键字后面跟的必须是一个可以等待的对象不然就会报错。


推荐阅读
  • 【图像分类实战】利用DenseNet在PyTorch中实现秃头识别
    本文详细介绍了如何使用DenseNet模型在PyTorch框架下实现秃头识别。首先,文章概述了项目所需的库和全局参数设置。接着,对图像进行预处理并读取数据集。随后,构建并配置DenseNet模型,设置训练和验证流程。最后,通过测试阶段验证模型性能,并提供了完整的代码实现。本文不仅涵盖了技术细节,还提供了实用的操作指南,适合初学者和有经验的研究人员参考。 ... [详细]
  • 通过使用CIFAR-10数据集,本文详细介绍了如何快速掌握Mixup数据增强技术,并展示了该方法在图像分类任务中的显著效果。实验结果表明,Mixup能够有效提高模型的泛化能力和分类精度,为图像识别领域的研究提供了有价值的参考。 ... [详细]
  • 开发日志:201521044091 《Java编程基础》第11周学习心得与总结
    开发日志:201521044091 《Java编程基础》第11周学习心得与总结 ... [详细]
  • Python全局解释器锁(GIL)机制详解
    在Python中,线程是操作系统级别的原生线程。为了确保多线程环境下的内存安全,Python虚拟机引入了全局解释器锁(Global Interpreter Lock,简称GIL)。GIL是一种互斥锁,用于保护对解释器状态的访问,防止多个线程同时执行字节码。尽管GIL有助于简化内存管理,但它也限制了多核处理器上多线程程序的并行性能。本文将深入探讨GIL的工作原理及其对Python多线程编程的影响。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • Objective-C 中的委托模式详解与应用 ... [详细]
  • 在Java编程中,`AbstractClassTest.java` 文件详细解析了抽象类的使用方法。该文件通过导入 `java.util.*` 包中的 `Date` 和 `GregorianCalendar` 类,展示了如何在主方法 `main` 中实例化和操作抽象类。此外,还介绍了抽象类的基本概念及其在实际开发中的应用场景,帮助开发者更好地理解和运用抽象类的特性。 ... [详细]
  • Android中将独立SO库封装进JAR包并实现SO库的加载与调用
    在Android开发中,将独立的SO库封装进JAR包并实现其加载与调用是一个常见的需求。本文详细介绍了如何将SO库嵌入到JAR包中,并确保在外部应用调用该JAR包时能够正确加载和使用这些SO库。通过这种方式,开发者可以更方便地管理和分发包含原生代码的库文件,提高开发效率和代码复用性。文章还探讨了常见的问题及其解决方案,帮助开发者避免在实际应用中遇到的坑。 ... [详细]
  • 本文深入解析了Java 8并发编程中的`AtomicInteger`类,详细探讨了其源码实现和应用场景。`AtomicInteger`通过硬件级别的原子操作,确保了整型变量在多线程环境下的安全性和高效性,避免了传统加锁方式带来的性能开销。文章不仅剖析了`AtomicInteger`的内部机制,还结合实际案例展示了其在并发编程中的优势和使用技巧。 ... [详细]
  • Python 实战:异步爬虫(协程技术)与分布式爬虫(多进程应用)深入解析
    本文将深入探讨 Python 异步爬虫和分布式爬虫的技术细节,重点介绍协程技术和多进程应用在爬虫开发中的实际应用。通过对比多进程和协程的工作原理,帮助读者理解两者在性能和资源利用上的差异,从而在实际项目中做出更合适的选择。文章还将结合具体案例,展示如何高效地实现异步和分布式爬虫,以提升数据抓取的效率和稳定性。 ... [详细]
  • 在Python多进程编程中,`multiprocessing`模块是不可或缺的工具。本文详细探讨了该模块在多进程管理中的核心原理,并通过实际代码示例进行了深入分析。文章不仅总结了常见的多进程编程技巧,还提供了解决常见问题的实用方法,帮助读者更好地理解和应用多进程编程技术。 ... [详细]
  • 利用ZFS和Gluster实现分布式存储系统的高效迁移与应用
    本文探讨了在Ubuntu 18.04系统中利用ZFS和Gluster文件系统实现分布式存储系统的高效迁移与应用。通过详细的技术分析和实践案例,展示了这两种文件系统在数据迁移、高可用性和性能优化方面的优势,为分布式存储系统的部署和管理提供了宝贵的参考。 ... [详细]
  • Java中不同类型的常量池(字符串常量池、Class常量池和运行时常量池)的对比与关联分析
    在研究Java虚拟机的过程中,笔者发现存在多种类型的常量池,包括字符串常量池、Class常量池和运行时常量池。通过查阅CSDN、博客园等相关资料,对这些常量池的特性、用途及其相互关系进行了详细探讨。本文将深入分析这三种常量池的差异与联系,帮助读者更好地理解Java虚拟机的内部机制。 ... [详细]
  • 本文详细介绍了使用 Python 进行 MySQL 和 Redis 数据库操作的实战技巧。首先,针对 MySQL 数据库,通过 `pymysql` 模块展示了如何连接和操作数据库,包括建立连接、执行查询和更新等常见操作。接着,文章深入探讨了 Redis 的基本命令和高级功能,如键值存储、列表操作和事务处理。此外,还提供了多个实际案例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 在MFC框架中,存在多个全局函数,用于在不同对象间获取信息或创建新对象。其中,`afxGetApp`函数尤为关键,它能够帮助开发者轻松获取当前应用程序的实例指针。本文将详细解析`afxGetApp`函数的内部机制及其在MFC应用程序中的具体应用场景,探讨其在提升代码可维护性和灵活性方面的优势。此外,还将介绍其他常用全局函数如`AfxWinInit()`和`AfxBeginThread()`的功能和使用方法,为开发者提供全面的参考。 ... [详细]
author-avatar
ngzhaicai9672364
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有