将Python的aiohttp集成到现有事件循环中。

17

我正在测试aiohttp和asyncio。 我希望同一个事件循环有一个套接字,HTTP服务器和HTTP客户端。

我正在使用这个示例代码:

@routes.get('/')
async def hello(request):
    return web.Response(text="Hello, world")

app = web.Application()
app.add_routes(routes)
web.run_app(app)

问题是run_app是阻塞的。我想将HTTP服务器添加到现有的事件循环中,该事件循环是使用以下方式创建的:

问题在于run_app是阻塞的。我想将HTTP服务器加入到已经创建的事件循环中:

asyncio.get_event_loop()
2个回答

23

问题在于run_app是阻塞的。我想将HTTP服务器添加到现有事件循环中。

run_app只是一个方便的API。要钩入现有事件循环,您可以直接实例化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()

在 asyncio 3.8 及更高版本中,您可以使用 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())

1
谢谢,为什么服务器不会在 SIGINT(按下 CTRL+C)时终止呢?我正在使用 Windows PowerShell。 - user3599803
@user3599803 不好意思,我没有使用Windows,但是通过搜索可能会发现这是asyncio中的一个长期存在的问题 - user4815162342
1
请查看此答案以在Windows机器上终止脚本:@user3599803 https://dev59.com/WV4c5IYBdhLWcg3w1dPx#37420223 - rsb
1
这里提供一个小提示,关于如何指定IP和端口,可能需要一些搜索:site = web.TCPSite(runner, host='0.0.0.0', port=80) - omegastripes

11
对于来自谷歌的未来旅行者,这里有一个更简单的方法。
async def main():
    await aio.gather(
        web._run_app(app, port=args.port),
        SomeotherTask(),
        AndAnotherTask()
    )

aio.run(main())

解释: web.runapp是对内部函数web._runapp的轻量级包装。该函数使用旧式的方式获取事件循环,然后调用loop.run_until_complete

我们将其替换为aio.gather以及其他要并发运行的任务,并使用aio.run来安排它们。

来源


2
他们现在提供了Application Runner API来允许这种用例:https://docs.aiohttp.org/en/stable/web_advanced.html#application-runners - Stuart Axon
7
请在StackOverflow答案中避免使用私有API。以“_”开头的方法,例如“_run_app”,可能会在没有事先通知的情况下被删除、重命名或更改含义。 - user4815162342
我在使用这个私有成员函数时遇到了困难,但是我能够使用应用程序运行示例 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接