【问题标题】:gevent clean Greenlet exitgevent clean Greenlet 出口
【发布时间】:2015-05-21 12:28:43
【问题描述】:

我想听听其他人对我看到的问题的解决方案,这是 gevent 用来向 greenlets 发出退出状态信号的默认方式。

我喜欢执行 group.kill(timeout = 3) 的能力,但它在 greenlet 中的翻译方式是生成 GreenletExit。这对于非常简单的本地计算代码来说很好,但我发现它对于任何更复杂的东西都非常有限。这是一个示例(使用 ZMQ):

def myGreenlet( zFrom, zTo ):
    msg = zFrom.recv_multipart()
    zTo.send_multipart( msg )

我希望能够告诉我的 greenlet 退出,但如果 GreenletExit 正在接收/传输任何内容,则忽略它。如果是这种情况,请发送您收到的任何消息,然后才干净地退出。

GreenletExit 只是瓷器店里的一头公牛。所以我想出的解决方案是除了作为最后的手段之外根本不使用该机制,而是手动处理向greenlet发送信号以通过这样的事件退出:

def myGreenlet( stopEvent, zFrom, zTo ):
    while not stopEvent.wait( 0 ):
        msg = zFrom.recv_multipart()
        zTo.send_multipart( msg )

您会注意到,这也不是很好,除非我开始在所有 IO 调用中添加超时(如 recv)并在 .wait() 中添加超时以减慢它的速度,这违背了哲学事件。

我在任何地方都在寻找更好的解决方案,但没有成功。普遍的共识是什么,有什么方法可以很好地解决这类问题?

【问题讨论】:

  • 显然对于第二个示例,我还可以在 zFrom 和 stopEvent 之间进行选择,但对于一个必须相当普遍的问题,它似乎仍然需要很多额外的代码。
  • 我的回答对你有启发吗?如果是这样,请接受我的回答,这对我很重要。谢谢。

标签: python gevent


【解决方案1】:

解决这个问题的更明智的方法是让每个 greenlet 处理自己的超时异常。 greenlet 协调员不应该对 greenlet 进行过多的干预。 coordinator应该做的是joinall他们,然后向greenlets询问结果或异常,这取决于它做一些后续操作。

详细解释:

def my_greenlet():
    try:
       # do something here...
    except KindOfTimeOutException, e:
       raise e

greenlets 协调员:

greenlets = [gevent.spawn(my_greenlet) for i range(10)]
gevent.joinall(greenlets)

# NOTE: On this time, the greenlets all have quit by themselves
for greenlet in greenlets:
    e = greenlet.exception
    if e:
        # handle exception...
    else:
        result = greenlet.value
        # do something...

【讨论】:

  • @user3395838 “这在协调器和 greenlet 之间引入了过多的耦合”,这就是我想对您说的关于您的问题的内容。在我的回答中,我让greenlets自己处理异常,而coordinator只检查结果。
  • @user3395838 我的解决方案和你的情况没有矛盾。 Actor 可以加入所有的 greenlets 并检查结果,然后决定是否稍后生成一些新的 greenlets。
猜你喜欢
  • 2012-12-09
  • 1970-01-01
  • 2021-03-04
  • 2020-01-31
  • 1970-01-01
  • 2013-06-20
  • 2018-03-05
  • 2019-04-10
  • 1970-01-01
相关资源
最近更新 更多