2016-04-01 7 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].value получил надлежащее значение из fooFn. Это означает, что была выполнена фишка threads[0].

Почему это произошло, когда я пропустил только роду threads[1] до gevent.joinall?

Как я могу убедиться, что выполнены только эти зеленые, которые фактически переданы в gevent.joinall?

+0

'gevent.joinall()' только ждет, что зеленые точки переданы в качестве параметров для завершения и соединяет его с основным потоком. Насколько мне известно, он не блокирует выполнение каких-либо других потоков - просто говорит основному потоку не выходить, пока зеленые панели не закончатся. –

ответ

3

Ваши зеленые плакаты запланированы немедленно при звонке greenlet.spawn(). Другими словами, они создаются и запускаются сразу, когда вы вызываете spawn(). Вот почему первая зелень завершена, и зелья выполнялись с того момента, когда вы их породили, и к тому времени, когда вы приблизились к поиску результатов от greenlet 1, оба были выполнены.

gevent.joinall() не выполняет зеленых - это указывает только на основной поток (тот, который на самом деле spawn их), чтобы ждать, пока те передаются в качестве параметров для завершения работы. Не звонит joinall рискует завершить и завершить основную нить до того, как будут достигнуты результаты зеленых в joinall(), а затем кто будет обрабатывать их результаты?

Здесь вы сделали две вещи, которые вы должны изменить для того, чтобы увидеть gevents ведут себя, как вы хотите:

  • Вы называемые joinall() в консоли РЕПЛ, а не из сценария.

    Здесь основная нить - РЕПЛ - это гарантированно не закончить перед возвращением greenlets, потому что РЕПЛ только заканчивается, когда вы звоните exit() или указать EOF. Однако в сценарии без непосредственного взаимодействия с пользователем у вас нет этой роскоши - выполнение заканчивается, когда в скрипте ничего не остается. Вот почему мы вызываем join(), чтобы гарантировать, что главная нить никогда не выйдет и не покинет вашу зеленую вилку, без родителя, чтобы вернуться.

    Там нет смысла в вызове joinall() в консоли (хотя, если вы хотите гарантировать, что вы будете иметь результаты от greenlet при следующем вызове функции на greenlet, это хорошая идея)

  • вы не должны 't позвонили spawn(), если вы хотите гарантировать, что только greenlet 1 выполняется, а greenlet 2 - нет.Вместо этого, read what the docs say:

    Чтобы начать новую greenlet, передать целевой функции и ее аргументы Greenlet конструктора и вызова запуска():

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

    >>> g.start()

    или использовать classmethod spawn() который является ярлыком, который делает то же самое:

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

Использование start для указания greenlet должен начать работать в данный момент является хорошей идеей. Итак: создайте два объекта greenlet и вызовите только start, чтобы один из них выполнял только один.