2016-04-01 58 views
0

我有以下Python代碼:爲什麼蟒蛇gevent.joinall執行所有greenlets

>>> 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

我如何確保只有那些實際上傳遞給gevent.joinall的greenlet被執行?

+0

'gevent.joinall()'只等待傳入的greenlet作爲參數完成並加入到主線程中。據我所知,它不會阻止任何其他線程的執行 - 只是告訴主線程在greenlet運行完成之前不要退出。 –

回答

3

當您撥打greenlet.spawn()時,您的greenlet將立即預定。換句話說,當您致電spawn()時,它們會立即創建並啓動。這就是爲什麼第一個greenlet完成運行的原因 - 從產生它們的那一刻開始,兩個greenlet都在執行,當你開始查找來自greenlet 1的結果時,兩者都執行完畢。

gevent.joinall()不會執行greenlet - 它只會告訴主線程(實際上是spawn編輯它們的那個線程)等待傳入的參數完成運行。在joinall()已經達成綠色小魚的結果之前,沒有呼叫joinall運行主線程完成和退出的風險,然後誰來處理它們的結果?

在這裏,你做了兩件事情,你應該爲了改變看gevents的行爲像你想:

  • 您在控制檯REPL稱爲joinall(),而不是從一個劇本。

    這裏,主線程 - 的REPL - 是保證 greenlets回來之前完不成,因爲當你調用exit() 或EOF表示REPL只有結束。然而,在沒有直接用戶交互的腳本中,您沒有這種奢侈 - 當腳本中沒有任何內容時,執行就會結束。這就是爲什麼我們打電話join()確保主線程永不退出,並讓您的greenlet掛着沒有父母返回。

    有在控制檯呼叫joinall()沒有點(但如果你想有一個保證,你將不得不從greenlet結果,當你下一次呼籲greenlet的功能,這是一個好主意)

  • 你不應該如果你想保證只有greenlet 1被執行,而greenlet 2沒有被執行,那麼你不需要調用spawn()。相反,read what the docs say

    要開始新的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以僅執行一個。