我有以下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].value
从fooFn
获得了适当的值。这意味着threads[0]
greenlet已被执行。
为什么当我仅将threads[1]
greenlet传递给gevent.joinall
时,会发生这种情况?
如何确保只执行实际传递给gevent.joinall
的那些greenlet?
答案 0 :(得分:4)
当您致电greenlet.spawn()
时,您的greenlet会立即立即安排。换句话说,当您致电spawn()
时,它们会立即创建并启动。这就是为什么第一个greenlet完成运行的原因 - 两个greenlet都是从你生成它们的那一刻开始执行的,当你到处查找greenlet 1的结果时,两个都已完成执行。
gevent.joinall()
没有执行greenlets - 它只告诉主线程(实际上spawn
编辑它们的那个)等待传入的线程作为参数完成运行。在调用joinall
中的greenlet结果之前,不调用joinall()
会导致主线程完成和退出的风险,然后谁将处理他们的结果?
在这里,你做了两件事情,你应该改变,以便看到gevents
表现得像你想要的那样:
您在控制台REPL中调用了joinall()
,而不是从脚本调用。
这里,主线程 - REPL - 保证在之前没有完成
greenlets返回,因为REPL仅在您调用exit()
时结束
或表示EOF。然而,在没有直接用户交互的脚本中,您没有那种奢侈 - 当脚本中没有任何内容可以执行时,执行就结束了。这就是为什么我们调用join()
来确保主线程永远不会退出并让你的greenlet挂起而没有父级返回。
在控制台中调用joinall()
没有任何意义(尽管如果您想要保证,当您下次调用greenlet上的某个函数时,您将获得greenlet的结果,那么&#39 ;一个好主意)
如果您想保证只执行greenlet 1而greenlet 2不是,则不应该调用spawn()
。{li>
要启动新的greenlet,请将目标函数及其参数传递给 Greenlet构造函数和调用start():
>>> g = Greenlet(myfunction, 'arg1', 'arg2', kwarg1=1)
>>> g.start()
或使用classmethod
spawn()
这是一个相同的快捷方式:
>>> g = Greenlet.spawn(myfunction, 'arg1', 'arg2', kwarg1=1)
使用start
表示此时应该开始运行的greenlet是个好主意。所以:创建两个greenlet对象,只在其中一个上调用start
,只执行那个。