ubzhna
Last Updated: January 28, 2019
·
552
· eallik

Gevent + Werkzeug longpolling/streaming

werkzeug.wrappers.Response actually takes any generator, not just a string or list of string or a "normal" iterator/generator. That includes those that yield values in a delayed manner, or indefinitely:

def mystream():
    while True:
        gevent.sleep(1.0)
        yield "Hello\n"

return Response(mystream())

or, you can have one or more greenlets send chunks to be turned into a streaming response:

ch = gevent.queue.Queue()  # gevent.queue.Channel will do just as well

def mystream():
    while True:
        yield json.dumps(ch.get()) + '\n'

def mydummyeventmonitor(name):
    while True:
        gevent.sleep(random.random() + .5)
        ch.put({
            'event': 'event-%s' % name,
            'value': random.randint(0, 100)
        })

gevent.spawn(mydummyeventmonitor, 'foo')
gevent.spawn(mydummyeventmonitor, 'bar')
return Response(mystream())

or, instead of mystream, just use iter(<fn>, <term>):

return Response(iter(lambda: json.dumps(ch.get()) + '\n', None))