Python——eventlet.event


  該模塊提供eventlet的事件支持,事件提供了跨 greenthread 的操作原語。

  同一個事件對象既可以發出事件也可以接收(等待)事件,不同的協程共享這一個事件對象,就為不同協程之間基於事件的同步提供了可能。

 

 class eventlet.event.Event 

  該類型抽象了以下事件:任意數量的協程可以等待其他一個協程發出的某一個事件。

  事件類似於一個只能容納一個對象的隊列,但是有以下兩個方面的區別:

  1. 調用 send() 絕不會取消對當前greenthread的調度;

  2. send() 只能被調用一次,想要再發一遍這個事件,那么不好意思,重新創建一個Event對象吧。

  事件對於協程之間交流結果非常有用,同時也是 GreenThread.wait() 實現的基礎。

  例如:

>>> from eventlet import event
>>> import eventlet
>>> evt = event.Event()
>>> def baz(b):
...     evt.send(b + 1)
...
>>> _ = eventlet.spawn_n(baz, 3)
>>> evt.wait()
4

 

該類主要的方法有:

  1. ready()

  2. send(result=None, exc=None)

  3. reset()

  4. send_exception(*args)

  5. wait()

 

class eventlet.event.Event的方法

 

1.  ready() 

  判斷一個Event對象有沒有發出過事件,如果調用 wait() 會立即返回一個事件結果,那么此處就返回真值。

  該方法用來避免等待那些需要一段時間才會超時的事件。例如,你可以將一堆時間放到一個Python列表中,然后重復地遍歷他們,這是就可以調用 ready() 直到其中的一個事件返回True,然后就可以立刻調用 wait() 來獲取它了。

 

2.  send(result=None, exc=None) 

  用 result 喚醒等待者,然后立刻返回給父對象。

  例如:

>>> from eventlet import event
>>> import eventlet
>>> evt = event.Event()
>>> def waiter():
...     print('about to wait')
...     result = evt.wait()
...     print('waited for {0}'.format(result))
>>> _ = eventlet.spawn(waiter)
>>> eventlet.sleep(0)
about to wait
>>> evt.send('a')
>>> eventlet.sleep(0)
waited for a

  一個event對象不能多次調用 send() 方法:

>>> evt.send('whoops')
Traceback (most recent call last):
...
AssertionError: Trying to re-send() an already-triggered event.

  可以在多次 send() 方法之間調用 reset() 來重用Event對象。注意使用 reset() 重置后調用 ready() 方法將返回假值,然后同一個Event對象又可以調用 send() 方法了。

 

3.  send_exception(*args) 

  作用類似於 send() 方法,只不過向等待者發送的是一個異常。

  該方法的參數和 raise 方法的參數完全相同,如果單個異常對象被傳進來,它會在 wait() 方法被調用的時候重新拋出,生成一個新的堆棧軌跡。

  例如:

>>> from eventlet import event
>>> evt = event.Event()
>>> evt.send_exception(RuntimeError())
>>> evt.wait()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "eventlet/event.py", line 120, in wait
    current.throw(*self._exc)
RuntimeError

  如果需要完整地保留堆棧軌跡,必須傳入整個 sys.exc_info() 元組。

>>> import sys
>>> evt = event.Event()
>>> try:
...     raise RuntimeError()
... except RuntimeError:
...     evt.send_exception(*sys.exc_info())
...
>>> evt.wait()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "eventlet/event.py", line 120, in wait
    current.throw(*self._exc)
  File "<stdin>", line 2, in <module>
RuntimeError

  此時會在Event對象內部存儲一個 traceback 對象,這可能會導致循環引用。詳見 sys.exc_info() 的文檔。

 

4.  wait() 

  等待直到另一個協程調用 send() 。返回其他協程傳遞給 send() 方法的值。

  例如:

>>> from eventlet import event
>>> import eventlet
>>> evt = event.Event()
>>> def wait_on():
...    retval = evt.wait()
...    print("waited for {0}".format(retval))
>>> _ = eventlet.spawn(wait_on)
>>> evt.send('result')
>>> eventlet.sleep(0)
waited for result

  最后的一句如果改為調用 wait() 方法的話,只要已經有一個協程已經發出過事件,此處會立即返回結果:

>>> evt.wait()
'result'

   *評:

  一個Event對象在 send() 以后,除非 reset() ,否則多次 wait() 也不會刪除 send() 時發出的值,再結合如果不 reset()send() 只能調用一次,不難理解為什么這里說是“多個協程等待其他一個協程發出某一個事件”了。

  自己寫了一個小劇本,放在這里解釋這個模塊:

import time
import eventlet
from eventlet import event
from eventlet import greenthread

evt = event.Event()

def Joker():
    i = 0
    while i < 3:
        print "Joker: Can anybody get me?"
        i += 1
        time.sleep(1)

    print evt.wait()
    print "Fighting."
    time.sleep(3)
    return "Joker: Sorry, you got missed."

def Batman():
    evt.send("Bat man: I'm coming for you!")
    return "Bat man: I'm back, and your day is coming soon!"

#Joker()
gt1 = greenthread.spawn(Joker)
gt2 = greenthread.spawn_after(5, Batman)

print gt1.wait()

time.sleep(1)
print gt2.wait()

time.sleep(2)
print "To be continued."

  

  哥譚鎮上有一臭名昭著的惡霸,人稱小丑Joker,他作惡多端,欺行霸市。但哥譚鎮的警察都收受了他的賄賂,所以他得以逍遙法外,為害蒼生。

  小丑猖狂無邊,覺得身邊的人都太無聊:小混混為非作歹都沒有創意,警察又太軟弱。這個世界上只有一個人能夠挑起他的好奇——蝙蝠俠。於是小丑不斷挑釁蝙蝠俠的底線,帶頭作亂3年后,等着蝙蝠俠上門這個事件的發生。

  蝙蝠俠深知小丑狡詐多變,雖對小丑極度憎惡,但老管家一直勸他 “Son, you have to be patient.”,於是潛心修煉。終於在5年后,蝙蝠俠復出下山,身形矯健,身手了得,發出事件 “I'm coming for you!”。

  蝙蝠俠與小丑大戰哥譚之巔,歷時三年,雙方戰得難解難分,眼見小丑即將落敗之際,使出陰險之計,誘騙蝙蝠俠保護平民,自己趁機遁逃。

  蝙蝠俠回身再戰,小丑早已不見蹤影,留下余音籠罩在哥譚鎮的上空:“Sorry, you got missed.” 蝙蝠俠環顧四周道 “Your day will come, since I am back!”。

  欲知后事如何,且聽下回分解。


免責聲明!

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



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