0

我有以下 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]greenlet被执行了。

为什么当我只通过threads[1]greenlet时会发生这种情况gevent.joinall

我怎样才能确保只执行那些实际传递给的greenlets gevent.joinall

4

1 回答 1

8

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

gevent.joinall()不执行greenlets - 它只告诉主线程(实际spawn编辑它们的线程)等待作为参数传入的那些完成运行。不调用joinall会冒主线程在joinall()到达 greenlets 的结果之前完成并退出的风险,然后谁来处理他们的结果?

在这里,您做了两件事情,您应该更改这些事情才能看到gevents您想要的行为:

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

    在这里,主线程 - REPL -保证不会在 greenlets 返回之前完成,因为 REPL 仅在您调用exit() 或指示 EOF 时结束。然而,在没有即时用户交互的脚本中,您没有那么奢侈 - 当脚本中没有任何事情可做时,执行结束。这就是为什么我们调用join()以确保主线程永远不会退出并且让您的greenlet 挂起并且没有父线程可以返回。

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

  • spawn()如果你想保证只执行 greenlet 1 而 greenlet 2 不执行,你就不应该打电话。相反,请阅读文档所说的内容

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

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

    >>> g.start()

    或使用 classmethodspawn()这是一个快捷方式,它做同样的事情:

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

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

于 2016-04-01T14:49:05.360 回答