我试图写一段代码来学习Python asyncio。其基本思想是:使用asyncio更新一些数据及时通过aiohttp呈现?
使用“简单的” Web服务器(aiohttp)一些数据呈现给用户
数据返回给用户将会改变及时
这里代码:
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()
问题是,代码正在运行(python 3.5),但是userfeed
总是空的浏览器和也web_handler()
:-(
- 为什么
userfeed
没有更新? - 关于这个
timely date update
函数,因为更新机制可能更复杂,以后说可能涉及异步IO等待,有没有更好的方法,而不是使用while True: await asyncio.sleep(3)
中的data_updater()
来得到“更精确”的定时器?
你想推动通知浏览你的网页的用户(没有任何他的行动)?如果是这样,你应该看看* websocket *技术,它在'aiohttp'中以一种非常简单的方式实现(有[示例](https://github.com/KeepSafe/aiohttp/blob/master/ examples/web_ws.py)在源代码中)。否则,你应该使用你的['app'对象](http://aiohttp.readthedocs.io/en/stable/faq.html#id3)(它提供了一个'dict'接口)来在函数之间传递'userfeed'变量并避免使其成为全球性的。 – mgc
@ mgc,谢谢你的回复。我不希望数据在用户的浏览器中自动刷新,只需一个客户端拉模型就足够了 - 每当用户通过浏览器或wget等工具打开URL时,最新的数据就会显示出来。这里的混淆是,为什么全局变量没有被更新(在'web_handler()'print内部显示它总是[],但是'data _updater()'打印它会改变)? async def与普通def不同,它会以某种方式缓存上下文吗? – user340307
查看我的答案的一个示例,因为在此上下文中使用全局变量明显不鼓励[documentation](http://aiohttp.readthedocs.io/en/stable/web.html#data-sharing-aka-no-单身-请)。但是,如果你真的需要使用全局'userfeed'来工作,只需在'data_updated'和'web_handle'函数中添加'global userfeed',它就可以工作(这样函数就知道'userfeed'指向一个变量位于全局范围内,在您的示例中,每个函数都有自己的本地'userfeed')。 – mgc