设为首页 收藏本站
查看: 703|回复: 0

[经验分享] Python——eventlet.event

[复制链接]

尚未签到

发表于 2015-11-30 09:39:38 | 显示全部楼层 |阅读模式
  该模块提供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!”。
  欲知后事如何,且听下回分解。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145190-1-1.html 上篇帖子: 测试开发Python培训:抓取新浪微博评论提取目标数据-技术篇 下篇帖子: Python中ValueError: invalid literal for int() with base 10 的实用解决办法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表