为什么python gevent.joinall执行所有的greenlet



我有以下Python代码:

>>> import gevent
>>> from gevent import monkey; monkey.patch_all()
>>>
>>> def fooFn(k):
...     return 'gevent_'+k
...
>>> threads = []
>>> threads.append(gevent.spawn(fooFn,'0'))
>>> threads.append(gevent.spawn(fooFn,'1'))
>>>
>>> gevent.joinall([threads[1]])
>>>
>>> print threads[1].value
gevent_1
>>> print threads[0].value
gevent_0
>>>

如上所述,threads[0].valuefooFn获得了适当的值。这意味着执行了threads[0]绿绿灯。

当我只将threads[1]绿绿灯传递给gevent.joinall时,为什么会发生这种情况?

如何确保只执行那些实际传递给gevent.joinall的greenlet?

当您调用greenlet.spawn()时,您的绿绿灯会立即安排。换句话说,它们是在您调用spawn()时立即创建和启动的。这就是为什么第一个greenlet已经运行完毕——两个greenlet从你生成它们的那一刻起就在执行,当你从greenlet 1中查找结果时,它们都已经执行完毕。

gevent.joinall()不执行greenlets——它只是告诉主线程(实际上是spawn执行它们的线程)等待作为参数传入的线程完成运行。不调用joinall会导致主线程在joinall()中的greenlets的结果到达之前完成并退出,然后谁来处理他们的结果?

在这里,您做了两件应该更改的事情,以便看到gevents的行为符合您的要求:

  • 您在控制台REPL中调用了joinall(),而不是从脚本中调用。

    这里,主线程REPL保证不会在greenlets返回,因为REPL仅在调用exit()时结束或者指示EOF。然而,在一个没有即时用户交互的脚本中,你就没有这种奢侈了——当脚本中没有什么可做的时候,执行就结束了。这就是为什么我们调用join()来确保主线程永远不会退出,并且让你的greenlet挂起,没有父线程可以返回。

    在控制台中调用joinall()是没有意义的(尽管如果你想保证下次在greenlet上调用函数时会从greenlet得到结果,这是个好主意)

  • 如果您想保证只执行greenlet 1,而不执行greenlet 2,则不应该调用spawn()。相反,请阅读文档中的内容:

    要启动新的greenlet,请将目标函数及其参数传递给Greenlet构造函数和调用start():

    >>> g = Greenlet(myfunction, 'arg1', 'arg2', kwarg1=1)

    >>> g.start()

    或者使用类方法spawn(),这是一个做同样事情的快捷方式:

    >>> g = Greenlet.spawn(myfunction, 'arg1', 'arg2', kwarg1=1)

使用start来指示greenlet此时应该开始运行是个好主意。所以:创建两个greenlet对象,只对其中一个对象调用start,以便只执行该对象。

相关内容

  • 没有找到相关文章

最新更新