iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >多任务—协程
  • 479
分享到

多任务—协程

协程 2023-01-31 00:01:22 479人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

一、协程简介 协程 协程,又称微线程,纤程。英文名Coroutine。   协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在

一、协程简介

协程

协程,又称微线程,纤程。英文名Coroutine。

 

协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。

通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定

 

协程和线程差异

在实现多任务时, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。 操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。

 

# 进程 启动多个进程 进程之间是由操作系统负责调用
# 线程 启动多个线程 真正被CPU执行的最小单位实际是线程
# 协程
    # 本质上是一个线程
    # 能够在多个任务之间切换来节省一些io时间
    # 协程中任务之间的切换也消耗时间,但是开销要远远小于进程线程之间的切换

 

简单实现协程

 import time
 
 
 def work1():
     while True:
         print("work1")
         yield
         time.sleep(0.5)
 
 
 def work2():
     while True:
         print("work2")
         yield
         time.sleep(0.5)
 
 
 if __name__ == "__main__":
     w1 = work1()
     w2 = work2()
     while True:
         next(w1)
         next(w2)
View Code

 

二、greenlet

为了更好使用协程来完成多任务,Python中的greenlet模块对其封装,从而使得切换任务变的更加简单

 from greenlet import greenlet
 import time
 
 
 def test1():
     while True:
         print("test1")
         # 切换gt2运行
         gt2.switch()
         time.sleep(1)
 
 def test2():
     while True:
         print("test2")
         # 切换gt1运行
         gt1.switch()
         time.sleep(1)
 
 gt1 = greenlet(test1)
 gt2 = greenlet(test2)
 # 切换gt1运行
 gt1.switch()
View Code

 

三、gevent

greenlet已经实现了协程,但是这个还得人工切换,是不是觉得太麻烦了,不要捉急,python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent

其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。

由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

1. gevent的使用

 import gevent
 
 
 def test(n):
     for i in range(n):
         print(gevent.getcurrent(), i)
 
 
 g1 = gevent.spawn(test, 5)
 g2 = gevent.spawn(test, 5)
 g3 = gevent.spawn(test, 5)
 
 g1.join()
 g2.join()
 g3.join()

# 执行结果:
<Greenlet at 0x7f688ad95748: test(5)> 0
<Greenlet at 0x7f688ad95748: test(5)> 1
<Greenlet at 0x7f688ad95748: test(5)> 2
<Greenlet at 0x7f688ad95748: test(5)> 3
<Greenlet at 0x7f688ad95748: test(5)> 4
<Greenlet at 0x7f688ad95948: test(5)> 0
<Greenlet at 0x7f688ad95948: test(5)> 1
<Greenlet at 0x7f688ad95948: test(5)> 2
<Greenlet at 0x7f688ad95948: test(5)> 3
<Greenlet at 0x7f688ad95948: test(5)> 4
<Greenlet at 0x7f688ad95a48: test(5)> 0
<Greenlet at 0x7f688ad95a48: test(5)> 1
<Greenlet at 0x7f688ad95a48: test(5)> 2
<Greenlet at 0x7f688ad95a48: test(5)> 3
<Greenlet at 0x7f688ad95a48: test(5)> 4
可以看到,3个greenlet是依次运行而不是交替运行
View Code

 

2. gevent切换执行

 import gevent
 
 
 def test(n):
     for i in range(n):
         print(gevent.getcurrent(), i)
         gevent.sleep(1)  # 用来模拟一个耗时操作,注意不是time模块中的sleep
 
 
 g1 = gevent.spawn(test, 5)
 g2 = gevent.spawn(test, 5)
 g3 = gevent.spawn(test, 5)
 
 g1.join()
 g2.join()
 g3.join()


# 执行结果:
<Greenlet at 0x7fe357a77748: test(5)> 0
<Greenlet at 0x7fe357a77948: test(5)> 0
<Greenlet at 0x7fe357a77a48: test(5)> 0
<Greenlet at 0x7fe357a77748: test(5)> 1
<Greenlet at 0x7fe357a77948: test(5)> 1
<Greenlet at 0x7fe357a77a48: test(5)> 1
<Greenlet at 0x7fe357a77748: test(5)> 2
<Greenlet at 0x7fe357a77948: test(5)> 2
<Greenlet at 0x7fe357a77a48: test(5)> 2
<Greenlet at 0x7fe357a77748: test(5)> 3
<Greenlet at 0x7fe357a77948: test(5)> 3
<Greenlet at 0x7fe357a77a48: test(5)> 3
<Greenlet at 0x7fe357a77748: test(5)> 4
<Greenlet at 0x7fe357a77948: test(5)> 4
<Greenlet at 0x7fe357a77a48: test(5)> 4
View Code

 

3. 给程序打补丁

 import gevent
 from gevent import monkey
 import random
 import time
 
 # 有耗时操作时需要
 monkey.patch_all()  # 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
 
 def test(name):
     for i in range(10):
         print(name, i)
         time.sleep(random.random())
 
 
 gevent.joinall([
     gevent.spawn(test, "test1"),
     gevent.spawn(test, "test2")
     ])

# 执行结果:
test1 0
test2 0
test2 1
test1 1
test1 2
test1 3
test2 2
test1 4
test1 5
test2 3
test1 6
test1 7
test2 4
test2 5
test1 8
test2 6
test2 7
test1 9
test2 8
test2 9
View Code

 

四、进程、线程、协程对比

通俗描述

  • 有一个老板想要开个工厂进行生产某件商品(例如剪子)

  • 他需要花一些财力物力制作一条生产线,这个生产线上有很多的器件以及材料这些所有的 为了能够生产剪子而准备的资源称之为:进程

  • 只有生产线是不能够进行生产的,所以老板的找个工人来进行生产,这个工人能够利用这些材料最终一步步的将剪子做出来,这个来做事情的工人称之为:线程

  • 这个老板为了提高生产率,想到3种办法:

    1. 在这条生产线上多招些工人,一起来做剪子,这样效率是成倍増长,即单进程 多线程方式

    2. 老板发现这条生产线上的工人不是越多越好,因为一条生产线的资源以及材料毕竟有限,所以老板又花了些财力物力购置了另外一条生产线,然后再招些工人这样效率又再一步提高了,即多进程 多线程方式

    3. 老板发现,现在已经有了很多条生产线,并且每条生产线上已经有很多工人了(即程序是多进程的,每个进程中又有多个线程),为了再次提高效率,老板想了个损招,规定:如果某个员工在上班时临时没事或者再等待某些条件(比如等待另一个工人生产完谋道工序 之后他才能再次工作) ,那么这个员工就利用这个时间去做其它的事情,那么也就是说:如果一个线程等待某些条件,可以充分利用这个时间去做其它事情,其实这就是:协程方式

简单总结

  1. 进程是资源分配的单位

  2. 线程是操作系统调度的单位

  3. 进程切换需要的资源很最大,效率很低

  4. 线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)

  5. 协程切换任务资源很小,效率高

  6. 多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发

 

五、图片下载器

 from gevent import monkey
 import gevent
 import urllib.request
 
 
 monkey.patch_all()
 
 def down_img(img_name, img_url):
     req = urllib.request.urlopen(img_url)
     content = req.read()
     with open(img_name, 'wb') as f:
         f.write(content)
 
 
 if __name__ == "__main__":
     gevent.joinall([
         gevent.spawn(down_img, "1.jpg", "网址"),
         gevent.spawn(down_img, "2.jpg", "网址"),
         ])
                                                                                  
View Code

 

--结束END--

本文标题: 多任务—协程

本文链接: https://www.lsjlt.com/news/181812.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 多任务—协程
    一、协程简介 协程 协程,又称微线程,纤程。英文名Coroutine。   协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在...
    99+
    2023-01-31
    协程
  • 多任务中进程、线程、协程
    为什么使用多任务有什么好处? 答:提高程序执行效率,实现同一时刻可以做二个以上的事情。 啦啦啦。。。重点来了 并行:任务数大于CPU核数,每个CPU就要执行多个任务,那肯定忙不过来,多个任务执行就需要排队等待上一任务执行完,才能执行下一任...
    99+
    2023-01-30
    线程 进程 协程
  • 多任务-----协程gevent的使用
    协程 一,迭代器iterable 能实现一定的数据,但是又不会占用很大的空间,协程切换任务资源小,效率高。如何判断某一类型是否可以迭代 from collections import Iterable


 print(isinstan...
    99+
    2023-01-31
    协程 gevent
  • 异步协程开发实战:基于PHP的多线程任务调度器
    异步协程开发实战:基于PHP的多线程任务调度器前言:随着互联网技术的不断发展,更多的网站和应用程序开始面临并发访问的需求。传统的同步编程方式已经无法满足这种需求,因为同步编程需要等待某个任务完成后才能执行下一个任务,导致程序的运行效率低下。...
    99+
    2023-12-09
    多线程 异步 协程
  • 使用python怎么在协程中增加任务
    使用python怎么在协程中增加任务?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。python主要应用领域有哪些1、云计算,典型应用OpenStack。2、WEB前端开发,众多...
    99+
    2023-06-14
  • py基础---多线程、多进程、协程
    目录 Python基础__线程、进程、协程 1、什么是线程(thread)? 2、什么是进程(process)? 3、进程和线程的区别...
    99+
    2023-01-31
    多线程 进程 基础
  • 详解Python的多任务进程
    目录1.基本概念2.线程和进程比较3.协程和线程的比较总结1.基本概念 定义含义并发:concurrency,同一时刻只能有一条指令执行,但是多个线程的对应的指令被快速轮换地执行并行...
    99+
    2024-04-02
  • 异步 PHP — 多进程、多线程和协程
    让我们看一下这段典型的 PHP 代码: function names(){ $data = Http::get('data.location/products')->json(); $names = []; foreach...
    99+
    2023-09-09
    servlet json java
  • Python实现多任务进程示例
    目录一、进程介绍二、线程和进程之间的对比三、Python 实现多进程四、进程之间的通信五、进程池之间的通信六、案例:文件批量复制一、进程介绍 进程:正在执行的程序,由程序、数据和进程...
    99+
    2024-04-02
  • Python 多线程处理任务实例
    目录美餐每天发一个用Excel汇总的就餐数据,我们把它导入到数据库后,行政办公服务用它和公司内的就餐数据进行比对查重。 初始实现是单线程,和import_records去掉多线程后的...
    99+
    2024-04-02
  • 利用 Python 实现多任务进程
    目录一、进程介绍二、线程和进程之间的对比三、使用多进程的优势1、拥有独立GIL2、效率高四、Python 实现多进程1、使用 process 类2、继承 process 类五、进程之...
    99+
    2024-04-02
  • 使用python怎么实现在协程中增加任务
    这篇文章主要介绍了使用python怎么实现在协程中增加任务,此处通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考价值,需要的朋友可以参考下:python是什么意思Python是一种跨平台的、具有解释性、编译性、互动性和面向...
    99+
    2023-06-06
  • 大规模任务处理:使用Golang WaitGroup和协程池
    在使用Golang进行大规模任务处理时,我们可以结合使用WaitGroup和协程池来提高并发执行的效率。首先,我们需要导入相应的包:...
    99+
    2023-10-08
    Golang
  • 进程同步:操作系统中任务的协同之舞
    进程同步问题 进程同步问题是当多个进程同时访问共享资源时发生的。这可能会导致以下问题: 争用条件:进程以非确定性顺序并发访问共享数据,导致不一致的结果。 死锁:两个或多个进程永久等待对方释放资源,导致系统停滞。 优先级反转:低优先级的进...
    99+
    2024-03-12
    在现代计算机系统中 进程是独立执行的程序 每个进程都有自己的地址空间和执行流。当多个进程并行执行时 可能会出现资源竞争 这可能会导致死锁或不一致。为了解决这个问题 操作系统提供了进程同步机制 以确保
  • PHP 多线程与 Go 协程对比?
    php 多线程和 go 协程都是高并发场景下的有效机制。多线程提供了强大的管理功能,但开销较大,而协程非常轻量,开销更小。在实战中,php 多线程适合并发爬虫等任务,而 go 协程更适合...
    99+
    2024-05-12
    go php
  • Python如何实现多线程处理任务
    小编给大家分享一下Python如何实现多线程处理任务,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!读取Excel数据 —> 发送到行政服务接口安全起见线上操作放在了晚上进行。运行时发现每条数据导入消耗1s多,晚上十点...
    99+
    2023-06-25
  • SpringBoot定时任务多线程实现示例
    测试Spring Boot定时任务冲突时,使用的线程数量 引入依赖: Spring Boot 2.6.1 <dependency> <group...
    99+
    2024-04-02
  • C#多线程系列之任务基础(二)
    目录判断任务状态再说父子任务组合任务/延续任务复杂的延续任务并行(异步)处理任务并行(同步)处理任务并行任务的 Task.WhenAny并行任务状态循环中值变化问题定时任务 Task...
    99+
    2024-04-02
  • C#多线程之任务的用法详解
    目录一.启动任务1.使用线程池的任务2.同步任务3.使用单独线程的任务二.任务的结果————Future三.连续的任务四.任务的层次结...
    99+
    2024-04-02
  • C#多线程系列之任务基础(三)
    目录TaskAwaiter延续的另一种方法另一种创建任务的方法实现一个支持同步和异步任务的类型Task.FromCanceled()如何在内部取消任务Yield 关键字补充知识点Ta...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作