python中的协程:greenlet和gevent

  • 协程是一中多任务实现方式,它不需要多个进程或线程就可以实现多任务。

1.通过yield实现协程:

代码:

import time

def 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 greenlet
import time

def 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)  #创建协程g1
g2 = greenlet(B)

g1.switch()  #跳转至协程g1

执行结果:

-------A-------
-------B-------
-------A-------
-------B-------
-------A-------
···

3.gevent:

  • greenlet可以实现协程,不过每一次都要人为的去指向下一个该执行的协程,显得太过麻烦。python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent
  • gevent每次遇到io操作,需要耗时等待时,会自动跳到下一个协程继续执行。

上代码:

import gevent

def A():
    while 1:
        print('-------A-------')
        gevent.sleep(1) #用来模拟一个耗时操作,注意不是time模块中的sleep

def 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 gevent
from gevent import monkey,socket

monkey.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()
            break

g1 = gevent.spawn(func_accept)
g1.join()
  • gevent的代码风格和线程非常相似,运行出来后的效果也非常相似。
相关文章
相关标签/搜索