我正在尝试编写一个片段来研究Python asyncio。基本思路是:
使用"简单" 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()
来获取"更粗略精确"计时器? 答案 0 :(得分:1)
主要问题是您忘记了global userfeed
和data_updater
函数中的语句web_handle
。因此,根据how python resolves scopes,在web_handle
中,它指的是您定义的全局变量,在data_updater
中指的是由userfeed = [x for x ...
语句创建的本地变量。在此上下文中使用全局变量是显式discouraged所以有一个示例使用dict
对象的aiohttp.web.Application
接口来安全地引用函数之间的变量。
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()
当您在127.0.0.1:8000
上刷新页面时,您应该有一些新的随机数,因为它们每3秒在服务器端更新一次(您可以将print
语句放回到data_updater
中验证它。)