zoukankan      html  css  js  c++  java
  • python 协程

    生成器复习

    在python中,使用了yield的函数被称为生成器(generator).

    跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单理解生成器就是一个迭代器.

    在调用生成器运行的过程中,每次遇到yield时函数会餐厅并保存当前所有的运行信息,返回yield的值,并在下一次执行next()方法时从当前位置继续运行.

    调用一个生成器函数,返回的是一个迭代器对象.

    ————摘自 noob python3教学。

    使用生成器的yield机制来实现多任务

    生成器制作方式,在函数中使用yield关键字,生成器。

     def work1():
      for i in range(10):
         print(F'----work1---{i}')
         yield
     def work2():
      for i in range(10):
         print(F'----work2---{i}')
         yield
     # 通过生成器实现多任务
    g1 = work1()
    g2 = work2()
     while True:
      next(g1)
      next(g2)

    这中方式可以称为简单的协程,又叫做微线程。

    协程本质上是单任务,只是利用了yield机制在多个任务切换交替执行。

    协程依赖于线程。

    协程对于线程来说占用的资源更少,几乎没有。

     

    协程概念理解

    又称微线程,英文名Coroutine

    1,什么是协程

    协程是python中一种实现多任务的方式,只不过比线程更小占用,更小执行单元(理解为需要的资源),自带cpu上下文。

    通俗的理解,在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息。

    然后切换到另一个函数中执行,注意不是通过调用函数的方式做到的切换,并且切换的次数以及什么时候切换回来都是由开发者决定。

    2,协程与线程差异

    在实现多任务时,线程切换从系统层面远不止保存和恢复cpu上下文这么简单,操作系统为了让程序运行的高效每个线程都有自己缓存cache等数据,

    操作系统还会帮忙做这些数据的恢复工作,所以线程的切换比较耗性能,但是协程的切换只是单纯的操作cpu的上下文,所以一秒钟切换上百万次系统都扛得住

    3,greenlet

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

    pip install greenlet

    def work1():
       for i in range(10):
          print(F'----work1---{i}')
          g2.switch()
    def work2():
       for i in range(10):
          print(F'----work2---{i}')
          g1.switch()
    g1 = greenlet(work1)
    g2 = greenlet(work2)
    g1.switch()

    但是greenlet不够优雅,必须要在协程内部写switch方法才能完成切换,可以使用gevent来代替

    4,gevent

    import  gevent
    from gevent import monkey
    monkey.patch_all()  # gevent 的不定
    def work1():
       for i in range(10):
          print(F'----work1---{i}')
          gevent.sleep(0.1)
    def work2():
       for i in range(10):
          print(F'----work2---{i}')
          gevent.sleep(0.1)
    # 创建两个携程
    # 线程默认不会等待携程执行
    # 携程存在于线程之中
    # spawn 开启协程(第一个参数为携程要执行的任务
    # join 让线程等待携程执行
    # 携程是在什么时候切换的呢?
    # 携程之间切换的条件
    # gevent.sleep()  耗时等待的情况下才会切换,,不写这个方法就不会切换
    # monkey.patch_all()  # gevent 补丁 使用一下这个代码就不需要在写gevent也可以交替执行
    # 首先考虑携程  --- 线程  --- 进程
    g1 = gevent.spawn(work1)
    g2 = gevent.spawn(work2)
    g1.join()
    g2.join()
    # 与主线程相比是异步

  • 相关阅读:
    HDU 6370 dfs+并查集
    牛客网暑期ACM多校训练营(第六场)G
    HDU 6351暴力枚举 6354计算几何
    2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 A,D
    2018 百度之星 初赛 第六题 HDU6349
    HDU 6336 子矩阵求和
    HDU 6333 莫队+组合数
    BZOJ 2308 莫队入门经典
    Linux系统管理第一章
    2019年7月17日
  • 原文地址:https://www.cnblogs.com/addicated/p/13175461.html
Copyright © 2011-2022 走看看