欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python之协程

程序员文章站 2022-07-07 19:30:49
一、什么协程 协程是指在单线程下实现并发,意思就是在一个线程中,实现任务之间的来回切换。我们之前讲的进程、线程,遇到IO阻塞,都是由操作系统来调度进行切换,不是有我们能控制的,但协程就是有我们来决定在哪进行切换。 二、用生成器实现任务之间的切换 三、用greenlet实现任务之间的切换 四、协程的实 ......

一、什么协程

  协程是指在单线程下实现并发,意思就是在一个线程中,实现任务之间的来回切换。我们之前讲的进程、线程,遇到io阻塞,都是由操作系统来调度进行切换,不是有我们能控制的,但协程就是有我们来决定在哪进行切换。

二、用生成器实现任务之间的切换

import time
def fun1(): for i in range(10): print('%s号学生'%i)
     time.sleep(1) yield def fun2(): g=fun1() for n in range(10): g.__next__() print('你好啊,%s号'%n)
     time.sleep(1) fun2()
这种模式虽然实现了任务间的切换,我们可以看到最终时间并没减少,也没实现并发

三、用greenlet实现任务之间的切换

import greenlet,time
def fun1():
    print('1111')
    g2.switch()
    time.sleep(1)
    print('2222')
    g2.switch()
def fun2():
    print('33333')
    g1.switch()
    time.sleep(1)
    print('4444')
g1=greenlet.greenlet(fun1)
g2=greenlet.greenlet(fun2)
fun1()
这也实现了任务间的切换,但最终运行时间也没缩短

四、协程的实现

  1,gevent模块的使用

#用法
g1=gevent.spawn(func,1,2,3,x=4,y=5)创建一个协程对象g1,spawn括号内第一个参数是函数名,如eat,后面可以有多个参数,可以是位置实参或关键字实参,都是传给函数eat的,spawn是异步提交任务

g2=gevent.spawn(func2)

g1.join() #等待g1结束,上面只是创建协程对象,这个join才是去执行

g2.join() #等待g2结束  有人测试的时候会发现,不写第二个join也能执行g2,是的,协程帮你切换执行了,但是你会发现,如果g2里面的任务执行的时间长,但是不写join的话,就不会执行完等到g2剩下的任务了

#或者上述两步合作一步:gevent.joinall([g1,g2])

g1.value#拿到func1的返回值

 ,2,协程的实现

#from gevent import monkey;monkey.patch_all()
import gevent,time #引入一个gevent模块 def fun1(): print('1111') gevent.sleep(1) #time.sleep(1) print('2222') def fun2(): print('333') gevent.sleep(1) #time.sleep(1) print('4444') g1=gevent.spawn(fun1,) #异步提交任务 g2=gevent.spawn(fun2,) gevent.joinall([g1,g2]) #等待
整个过程是:异步提交了fun1,和fun2。假如fun1先执行,先打印‘1111’,遇到io,切换到fun2,打印‘333’,遇到io,等到fun1的io过了之后有执行fun1,打印‘2222’。此时fun2的io也过了,也就执行fun2,打印‘4444’。
fun1的io是不会受到影响的,fun2也是,都在异步执行的

  进程线程的任务切换是由操作系统自行切换的,你自己不能控制

  协程是通过自己的程序(代码)来进行切换的,自己能够控制,只有遇到协程模块能够识别的io操作的时候,程序才会进行任务切换,实现并发效果,如果所有程序都没有io操作,那么就基本属于串行执行了。