use asyncio update some data timely and present via aiohttp?
<p>I am in trying to write a snippet to study Python asyncio. The basic idea is:</p>

<ol>
<li><p>use a "simple" web server (aiohttp) to present some data to user   </p></li>
<li><p>the data return to user will change promptly</p></li>
</ol>

<p>here is the code:</p>

<pre><code>import asyncio
import random
from aiohttp import web

userfeed = [] # the data suppose to return to the user via web browsers 

async def data_updater():  #to simulate data change promptly
    while True:
        await asyncio.sleep(3)
        userfeed = [x for x in range(random.randint(1, 20))]
        print('user date updated: ', userfeed)


async def web_handle(request):
    text = str(userfeed)
    #print('in handler:', text)  # why text is empty?
    return web.Response(text=text)

async def init(loop):
    app = web.Application(loop=loop)
    app.router.add_route('GET', '/', web_handle)
    srv = await loop.create_server(app.make_handler(), '127.0.0.1', 8000)
    print('Server started @ http://127.0.0.1:8000...')
    return srv

loop = asyncio.get_event_loop()
asyncio.ensure_future(data_updater())  
asyncio.ensure_future(init(loop))
loop.run_forever()
</code></pre>

<p>the problem is, the code is running (python 3.5), but the <code>userfeed</code> is always empty in browsers and also in <code>web_handler()</code> :-(</p>

<ol>
<li>why <code>userfeed</code> is not been updated?</li>
<li>regarding this <code>timely date update</code> function, because the update mechanism might be more complex later say async IO wait may be involved, is there a better way instead of using <code>while True: await asyncio.sleep(3)</code> in <code>data_updater()</code> to get "more roughly precise" timer? </li>
</ol>

<p>The main problem is that you forget the statement <code>global userfeed</code> in both <code>data_updater</code> and <code>web_handle</code> functions. So, according to <a href="http://stackoverflow.com/a/292502/5050917">how python resolves scopes</a>, in <code>web_handle</code> it was referring to the global variable you defined and in <code>data_updater</code> to a local one, created by the statement <code>userfeed = [x for x ...</code>. Using global variables in this context is explicitly <a href="http://aiohttp.readthedocs.io/en/stable/web.html#data-sharing-aka-no-singletons-please" rel="nofollow">discouraged</a> so there is an example using the <code>dict</code> interface of the <code>aiohttp.web.Application</code> object to safely refer to your variable between the functions.</p>

<pre><code>import asyncio
import random
from aiohttp import web


async def data_updater(app):
    while True:
        await asyncio.sleep(3)
        app["userfeed"] = [x for x in range(random.randint(1, 20))]

async def web_handle(request):
    userfeed = request.app["userfeed"]
    return web.Response(text=str(userfeed))

async def init(loop, port=8000):
    app = web.Application(loop=loop)
    app.router.add_route('GET', '/', web_handle)
    handler = app.make_handler()
    srv = await loop.create_server(
        handler, '127.0.0.1', port=port)
    return srv, app, handler

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    srv, app, handler = loop.run_until_complete(init(loop, 8000))
    app['userfeed'] = []
    asyncio.ensure_future(data_updater(app))
    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        srv.close()
        loop.run_until_complete(srv.wait_closed())
        loop.run_until_complete(app.shutdown())
        loop.run_until_complete(handler.finish_connections(60.0))
        loop.run_until_complete(app.cleanup())
    loop.close()
</code></pre>

<p>When you refresh the page on <code>127.0.0.1:8000</code> you should have some new random numbers as they are updated every 3 seconds server-side (you can put back the <code>print</code> statement in <code>data_updater</code> to verify it).</p>

python python-asyncio aiohttp