生成器复习
在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() # 与主线程相比是异步