python中的協程:greenlet和gevent


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的代碼風格和線程非常相似,運行出來后的效果也非常相似。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM