gevent是基於libev和greenlet的一個python異步框架。python
libev是一個高性能的事件循環(event loop)實現。
事件循環(也稱做IO多路複用),是解決阻塞問題,實現併發的一種方法。簡單點說,就是event loop
會捕獲、處理io
事件的變化:遇到阻塞,就跳出;阻塞結束,就繼續。這依賴於系統底層的select
函數及其升級版:poll
和epoll
。《深刻理解計算機系統》一書中,對此有深刻探討。git
greenlet
是一個python
的協程管理、切換模塊。經過greenlet
,你能夠顯式地在不一樣的任務之間切換。github
Actor
是Erlang
語言的精髓。它強調基於消息傳遞的併發機制。
咱們模仿這篇文章 創建一個actor模型。核心代碼以下:併發
import genvet # 主隊列 queue = gevent.queue.JoinableQueue() while True: # 持續獲取數據 try: data = queue.get(timeout=5) except Empty: gevent.sleep(0.5) continue # 交付給Actor if data: gl = Actor(data) g1.start() g1.join()
Actor
爲咱們自定義的一個Greenlet
的子類,核心代碼以下:框架
class Actor(Greenlet): def __init__(self, data): self.data = data Greenlet.__init__(self) def _run(self): result = do_something(self.data) return result
這樣,咱們這個Actor
能夠從消息隊列中接受數據,經過start()
,_run()
被調用。異步
因爲gevent
和monkey patch
的存在,你基本能夠以同步的方式,寫出異步的代碼。這樣的寫法顯得不少餘。可是,卻能夠很好的實現業務的分離,讓代碼更清晰,更容易維護和擴展。函數
若是你還但願給Actor
加一個回調。即等他完成了以後,再進行某些處理。
那咱們能夠對Actor
機型以下修改:oop
class Actor(Greenlet): def __init__(self, data): self.data = data Greenlet.__init__(self) def _run(self): # 經過self.link添加回調函數。 self.link(callback) result = do_something(self.data) return result
你能夠經過Greenlet().link()
,給你的協程添加一個回調。這個回調函數只接收一個參數,即這個協程的實例(g1
)。咱們會看到_run()
函數,實際上是返回了一個結果result
的。那咱們在回調函數中可否取得這個值呢。實際上是能夠的,這個值被存在了g1.value
中。性能
仍是那句話,這樣的設計,可能看起來不少餘。但隨着框架功能的增長,這樣多餘的設計會讓你的代碼,愈發地靈活。.net