协程gevent模块的使用

前言:

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

通俗的描述:

  • 协程看做是是线程中的一个特殊的函数,这个函数执行的时候,可以在某个地方暂停,并且可以重新在暂停处,继续运行,协程在进行切换的时候,只需要保存当前协程函数中的一些临时变量等信息,然后切换到另外一个函数中执行,并且切换的次数以及什么时候再切换到原来的函数,都可以由开发者自己决定

  • 协成切换的时候,既不涉及到资源切换,也不涉及到操作系统的调度,而是在在同一个程序中切换不同的函数执行,所以协成占用的资源非常少,切换得时候几乎不耗费什么资源。

  • 协程与进程、线程相比并不是一个维度的概念

  • 协程有分为原生协程和第三方库(gevent模块)实现的协程两种

一、协程的第三方库:gevent模块:

官方文档:https://www.gevent.org/api/gevent.html

  1. 什么是gevent

    gevent 其原理是当一个协程遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

  2. 协程正常的情况下:遇到异步耗时(IO操作)才会进行切换

    I: input 输入(文件读取,网络请求数据接收)
    o: output 输出(往文件中写内容,发送网络请求)

  3. gevent模式的具体使用

    第一步:在程序中如果希望遇到IO和耗时就进行切换协程中执行,则需要添加补丁
    打补丁的作用是:将普通的耗时和IO操作—>转换为异步耗时和IO操作

    from gevent import monkey
    # 对所有的IO和耗时操作打补丁
    monkey.patch_all()    
    

    第二步:创建并启动协程:gevent.spawn(任务函数)

    # 1. 创建协程对象
    g1 = gevent.spawn(func1)     # 等待协程g1执行结束
    g2 = gevent.spawn(func2)     # 等待协程g2执行结束
    

    第三步:等待协程执行结束

    1. 第一种: join()方法

      #  2、单个协程对象执行结束
      g1.join()
      g2.join()
      
    2. 第二种: gevent.joinall([a,b])

      #  3、多个协程对象时等待协程执行结束
      gevent.joinall([g1,g2])
      
  4. 实现没有异步耗时(IO操作)时协程是不会执行的

    # 函数 1
    def func1():
        for i in range(3):
            print("=========== 正在做事情1 ============")
            time.sleep(1)     # time模块的等待并不会执行
    
    # 函数 2
    def func2():
        for i in range(4):
            print("=========== 正在做事情2 ============")
            time.sleep(1)
    
    # 1. 创建协程对象
    g1 = gevent.spawn(func1)     # 等待协程g1执行结束
    g2 = gevent.spawn(func2)     # 等待协程g2执行结束
    
    # #  2、等待协程执行结束
    # g1.join()
    # g2.join()
    
    #  3、多个协程对象时等待协程执行结束
    gevent.joinall([g1,g2])
    
    print("========================== 执行结束 ==========================")
    

    执行结果:

    1. 在上述代码中,去创建协程对象,等待执行结束后,发现两个任务还是一个一个的去执行,并没有同时去执行,这是因为协程只有遇到IO耗时等待的时候才会去执行,而代码中并没有涉及到IO耗时等待的操作,time模块的等待并不会触发。
      在这里插入图片描述
  5. 实现有异步耗时(IO操作)时协程的执行情况

    1. 第一种方式:通常情况下如果要协程去执行,就需要代码里涉及到IO等耗时操作,gevent模快中也有一个sleep方法:

      # 函数1
      def func1():
          for i in range(3):
              print("=========== 正在做事情1 ============")
              gevent.sleep(1)   # 这是异步耗时等待
      
      # 函数2
      def func2():
          for i in range(4):
              print("=========== 正在做事情2 ============")
              gevent.sleep(1)   # 这是异步耗时等待
      
      # 1. 创建协程对象
      g1 = gevent.spawn(func1)     # 等待协程g1执行结束
      g2 = gevent.spawn(func2)     # 等待协程g2执行结束
      
      #  2、多个协程对象时等待协程执行结束
      gevent.joinall([g1,g2])
      
      print("========================== 执行结束 ==========================")
      

      执行结果:

      1. 在上述代码中,去创建协程对象,等待执行结束后,发现两个任务是并行去执行是,代码中有涉及到IO耗时等待的操作,gevent.sleep(1), 协程遇到IO耗时等待的时候就会去执行。
        在这里插入图片描述
    2. 第二种方式:通常情况下如果要协程去执行,就需要代码里涉及到IO等耗时操作,也可以通过打补丁的方式去执行:

      from gevent import monkey
      
      # 对所有的IO和耗时操作打补丁
      monkey.patch_all()
      
      # 函数1
      def func1():
          for i in range(3):
              print("=========== 正在做事情1 ============")
              time.sleep(1)   
      
      # 函数2
      def func2():
          for i in range(4):
              print("=========== 正在做事情2 ============")
              time.sleep(1)   
      
      # 1. 创建协程对象
      g1 = gevent.spawn(func1)     # 等待协程g1执行结束
      g2 = gevent.spawn(func2)     # 等待协程g2执行结束
      
      #  2、多个协程对象时等待协程执行结束
      gevent.joinall([g1,g2])
      
      print("========================== 执行结束 ==========================")
      

      执行结果:

      1. 在上述代码中,首先去进行了打补丁的操作,在实现等待的方式上,使用了time模块,去创建协程对象,等待执行结束后,发现两个任务是并行去执行是,这是因为monkey在进行补丁操作时,自动将普通的耗时和IO操作—>转换为异步耗时和IO操作去执行,所以看到两个任务是并行去执行是。
        在这里插入图片描述
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值