0

gevent で原始的なプロデューサー/コンシューマー スクリプトを実行しています。ものを に入れるいくつかのプロデューサー関数とgevent.queue.Queue、キューからそれらを再度フェッチする 1 つのコンシューマー関数を開始します。

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 にあります。

4

1 に答える 1