У меня есть примитивный сценарий производителя/потребителя, работающий в gevent. Он запускает несколько функций-производителей, которые помещают объекты в gevent.queue.Queue
, и одну функцию-потребитель, которая снова извлекает их из очереди:
from __future__ import print_function
import time
import gevent
import gevent.queue
import gevent.monkey
q = gevent.queue.Queue()
# define and spawn a consumer
def consumer():
while True:
item = q.get(block=True)
print('consumer got {}'.format(item))
consumer_greenlet = gevent.spawn(consumer)
# define and spawn a few producers
def producer(ID):
while True:
print("producer {} about to put".format(ID))
q.put('something from {}'.format(ID))
time.sleep(0.1)
# consumer_greenlet.switch()
producer_greenlets = [gevent.spawn(producer, i) for i in range(5)]
# wait indefinitely
gevent.monkey.patch_all()
print("about to join")
consumer_greenlet.join()
Он отлично работает, если я позволяю gevent обрабатывать планирование неявно (например, вызывая time.sleep или какую-либо другую функцию gevent.monkey.patch()
ed), однако, когда я переключаюсь на потребителя явно (заменяю time.sleep
закомментированным вызовом switch
), gevent вызывает AssertionError:
Traceback (most recent call last):
File "/my/virtualenvs/venv/local/lib/python2.7/site-packages/gevent/greenlet.py", line 327, in run
result = self._run(*self.args, **self.kwargs)
File "switch_test.py", line 14, in consumer
item = q.get(block=True)
File "/my/virtualenvs/venv/lib/python2.7/site-packages/gevent/queue.py", line 201, in get
assert result is waiter, 'Invalid switch into Queue.get: %r' % (result, )
AssertionError: Invalid switch into Queue.get: ()
<Greenlet at 0x7fde6fa6c870: consumer> failed with AssertionError
Я хотел бы использовать явное переключение, потому что в производстве у меня много производителей, планирование gevent не выделяет достаточно времени выполнения потребителю, а очередь становится все длиннее и длиннее (что плохо). В качестве альтернативы приветствуется любое понимание того, как настроить или изменить планировщик gevent.
Это на Python 2.7.2, gevent 1.0.1 и greenlet 0.4.5.