python中的協程:greenlet和gevent

python中的協程:greenlet和gevent

  • 協程是一中多任務實現方式,它不須要多個進程或線程就能夠實現多任務。

1.經過yield實現協程:

代碼:python

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是在這方面作了改進。

上代碼:socket

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

執行結果:spa

-------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()

執行結果:code

-------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的代碼風格和線程很是類似,運行出來後的效果也很是類似。
相關文章
相關標籤/搜索