I'm testing aiohttp and asyncio. I want the same event loop to have a socket, http server, http client.
I'm using this sample code:
@routes.get('/')
async def hello(request):
return web.Response(text="Hello, world")
app = web.Application()
app.add_routes(routes)
web.run_app(app)
The problem is run_app
is blocking. I want to add the http server into an existing event loop, that I create using:
asyncio.get_event_loop()
The problem is
run_app
is blocking. I want to add the http server into an existing event loop
run_app
is just a convenience API. To hook into an existing event loop, you can directly instantiate the AppRunner
:
loop = asyncio.get_event_loop()
# add stuff to the loop
...
# set up aiohttp - like run_app, but non-blocking
runner = aiohttp.web.AppRunner(app)
loop.run_until_complete(runner.setup())
site = aiohttp.web.TCPSite(runner)
loop.run_until_complete(site.start())
# add more stuff to the loop
...
loop.run_forever()
In asyncio 3.8 and later you can use asyncio.run()
:
async def main():
# add stuff to the loop, e.g. using asyncio.create_task()
...
runner = aiohttp.web.AppRunner(app)
await runner.setup()
site = aiohttp.web.TCPSite(runner)
await site.start()
# add more stuff to the loop, if needed
...
# wait forever
await asyncio.Event().wait()
asyncio.run(main())
For the future traveler from Google, here is a simpler way.
async def main():
await aio.gather(
web._run_app(app, port=args.port),
SomeotherTask(),
AndAnotherTask()
)
aio.run(main())
Explanation: web.runapp
is a thin wrapper over internal function web._runapp
. The function uses the old style way of getting the eventloop and then calling loop.run_until_complete
.
We replace it with aio.gather
alongside other tasks that we want to run concurrently and use the aio.run
to schedule them
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.