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()
# 与主线程相比是异步

原文地址:https://www.cnblogs.com/addicated/p/13175461.html