为什么python gevent.joinall会执行所有greenlet
我有以下Python代码:为什么python gevent.joinall会执行所有greenlet,python,gevent,greenlets,Python,Gevent,Greenlets,我有以下Python代码: >>> import gevent >>> from gevent import monkey; monkey.patch_all() >>> >>> def fooFn(k): ... return 'gevent_'+k ... >>> threads = [] >>> threads.append(gevent.spawn(fooFn,'0'))
>>> 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
获取了一个正确的值。这意味着执行了线程[0]
greenlet
当我只将线程[1]
greenlet传递给gevent.joinall
时,为什么会发生这种情况
如何确保只执行那些实际传递给
gevent.joinall
的greenlet?调用greenlet.spawn()
时,您的greenlet会立即被调度。换句话说,当您调用spawn()
时,会立即创建并启动它们。这就是为什么第一个greenlet完成了运行——两个greenlet都是从您生成它们的那一刻开始执行的,当您开始查找greenlet 1的结果时,它们都完成了执行
gevent.joinall()
不执行greenlet-它只告诉主线程(实际生成它们的线程)等待作为参数传入的线程完成运行。不调用joinall
会导致主线程在到达joinall()
中的greenlet结果之前完成并退出,那么谁来处理它们的结果呢
在这里,为了看到gevents
的行为符合您的要求,您做了两件应该更改的事情:
- 您在控制台REPL中调用了
,而不是从脚本调用的 在这里,主线程REPL保证不会在 greenlet返回,因为REPL仅在调用joinall()
exit()时结束 或表示EOF。然而,在一个没有即时用户交互的脚本中,你没有那种奢侈的享受——当脚本中没有什么事情可做时,执行就结束了。这就是为什么我们调用
join() 在控制台中调用
没有任何意义(尽管如果您想要保证下次在greenlet上调用函数时,您将从greenlet获得结果,这是一个好主意)joinall()
- 如果要保证只执行greenlet 1而不执行greenlet 2,则不应该调用
。而是: 要启动新的greenlet,请将目标函数及其参数传递给 Greenlet构造函数和调用start():spawn()
>g=Greenlet(myfunction,'arg1','arg2',kwarg1=1)
或者使用classmethod>g.start()
,这是一个具有相同功能的快捷方式: g=Greenlet.spawn(myfunction,'arg1','arg2',kwarg1=1)spawn()
使用
start
指示greenlet此时应开始运行是一个好主意。因此:创建两个greenlet对象,并仅对其中一个对象调用start
,以仅执行该对象 当您调用greenlet.spawn()
时,您的greenlet将立即被调度。换句话说,当您调用spawn()
时,会立即创建并启动它们。这就是为什么第一个greenlet完成了运行——两个greenlet都是从您生成它们的那一刻开始执行的,当您开始查找greenlet 1的结果时,它们都完成了执行
gevent.joinall()
不执行greenlet-它只告诉主线程(实际生成它们的线程)等待作为参数传入的线程完成运行。不调用joinall
会导致主线程在到达joinall()
中的greenlet结果之前完成并退出,那么谁来处理它们的结果呢
在这里,为了看到gevents
的行为符合您的要求,您做了两件应该更改的事情:
- 您在控制台REPL中调用了
,而不是从脚本调用的 在这里,主线程REPL保证不会在 greenlet返回,因为REPL仅在调用joinall()
exit()时结束 或表示EOF。然而,在一个没有即时用户交互的脚本中,你没有那种奢侈的享受——当脚本中没有什么事情可做时,执行就结束了。这就是为什么我们调用
join() 在控制台中调用
没有任何意义(尽管如果您想要保证下次在greenlet上调用函数时,您将从greenlet获得结果,这是一个好主意)joinall()
- 如果要保证只执行greenlet 1而不执行greenlet 2,则不应该调用
。而是: 要启动新的greenlet,请将目标函数及其参数传递给 Greenlet构造函数和调用start():spawn()
>g=Greenlet(myfunction,'arg1','arg2',kwarg1=1)
或者使用classmethod>g.start()
,这是一个具有相同功能的快捷方式: g=Greenlet.spawn(myfunction,'arg1','arg2',kwarg1=1)spawn()
start
指示greenlet此时应开始运行是一个好主意。因此:创建两个greenlet对象,并仅对其中一个对象调用start
,以仅执行该对象 gevent.joinall()
只等待作为参数传入的greenlet完成并将其与主线程连接。据我所知,它不会阻止任何其他线程的执行—只是告诉主线程在Greenlet完成运行之前不要退出。gevent.joinall()
只等待作为参数传入的Greenlet完成并将其与主线程连接。据我所知,这是真的