我試圖寫一段代碼來學習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