python中的协程:greenlet和gevent
- 协程是一中多任务实现方式,它不需要多个进程或线程就可以实现多任务。
1.通过yield实现协程:
代码:
import timedef A(): while 1: print('------A-----') time.sleep(0.1) yield()def B(): while 1: print('-------B-----') time.sleep(0.1) next(a)a = A()B()
执行结果:
-------B-----------A------------B-----------A------------B-----------A------------B-----------A------------B-----------A-----···
2.greenlet:
- yield能实现协程,不过实现过程不易于理解,greenlet是在这方面做了改进。
上代码:
from greenlet import greenletimport timedef A(): while 1: print('-------A-------') time.sleep(0.5) g2.switch()def B(): while 1: print('-------B-------') time.sleep(0.5) g1.switch()g1 = greenlet(A) #创建协程g1g2 = greenlet(B)g1.switch() #跳转至协程g1
执行结果:
-------A--------------B--------------A--------------B--------------A-------···
3.gevent:
- greenlet可以实现协程,不过每一次都要人为的去指向下一个该执行的协程,显得太过麻烦。python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent
- gevent每次遇到io操作,需要耗时等待时,会自动跳到下一个协程继续执行。
上代码:
import geventdef A(): while 1: print('-------A-------') gevent.sleep(1) #用来模拟一个耗时操作,注意不是time模块中的sleepdef B(): while 1: print('-------B-------') gevent.sleep(0.5) #每当碰到耗时操作,会自动跳转至其他协程g1 = gevent.spawn(A) # 创建一个协程g2 = gevent.spawn(B)g1.join() #等待协程执行结束g2.join()
执行结果:
-------A--------------B--------------B--------------A--------------B--------------B--------------A--------------B--------------B-------···
4.协程gevent完成回显服务器:
import geventfrom gevent import monkey,socketmonkey.patch_all() #有IO才做时需要这一句s = socket.socket(2,1) #用的都是gevent模块中的socket,但用法一样s.setsockopt(1,2,1)s.bind(('',8080))s.listen(1024)def func_accept(): while 1: cs,userinfo = s.accept() print('来了一个客户'+str(userinfo)) g = gevent.spawn(func_recv,cs) #每当有用户连接,增加一条协程def func_recv(cs): while 1: recv_data = cs.recv(1024) print(recv_data) #程谁堵塞了,便会跳转至其他协程 if len(recv_data) > 0: cs.send(recv_data) else: cs.close() breakg1 = gevent.spawn(func_accept)g1.join()
- gevent的代码风格和线程非常相似,运行出来后的效果也非常相似。