How to run an aiohttp server in a thread?

前端 未结 4 938
独厮守ぢ
独厮守ぢ 2021-01-18 02:18

This example of aiohttp server in a thread fails with an RuntimeError: There is no current event loop in thread \'Thread-1\'. error:

import thre         


        
相关标签:
4条回答
  • 2021-01-18 02:19

    There's a new API intended for this use case:

    https://docs.aiohttp.org/en/stable/web_advanced.html#application-runners

    from aiohttp import web
    import asyncio
    
    
    async def healthz(request):
        return web.Response(text="OK")
    
    app = web.Application()
    app.add_routes([web.get("/", healthz)])
    
    
    async def runner():
        runner = web.AppRunner(app)
        await runner.setup()
        site = web.TCPSite(runner, "localhost", 8080)
        await site.start()
    
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(runner())
    
    
    0 讨论(0)
  • 2021-01-18 02:23

    It's possible to use web.run_app, just create a new event loop (and set handle_signals=False to avoid RuntimeError: set_wakeup_fd only works in main thread):

    import threading
    import asyncio
    from aiohttp import web
    
    def aiohttp_server():
        def say_hello(request):
            return web.Response(text='Hello, world')
    
        asyncio.set_event_loop(asyncio.new_event_loop())  # create a new event loop here
        app = web.Application(debug=True)
        app.add_routes([web.get('/', say_hello)])
        web.run_app(app, handle_signals=False)
    
    0 讨论(0)
  • 2021-01-18 02:31

    Create handler in main thread and manually create an event loop in child thread.

    import asyncio
    import threading
    from aiohttp import web
    
    
    def aiohttp_server():
        def say_hello(request):
            return web.Response(text='Hello, world')
    
        app = web.Application(debug=True)
        app.add_routes([web.get('/', say_hello)])
        handler = app.make_handler()
        return handler
    
    
    def run_server(handler):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        server = loop.create_server(handler, host='127.0.0.1', port=8089)
        loop.run_until_complete(server)
        loop.run_forever()
    
    
    t = threading.Thread(target=run_server, args=(aiohttp_server(),))
    t.start()
    

    Update

    For new aiohttp, use the following, thank @Auyer for notification.

    import asyncio
    import threading
    from aiohttp import web
    
    
    def aiohttp_server():
        def say_hello(request):
            return web.Response(text='Hello, world')
    
        app = web.Application()
        app.add_routes([web.get('/', say_hello)])
        runner = web.AppRunner(app)
        return runner
    
    
    def run_server(runner):
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(runner.setup())
        site = web.TCPSite(runner, 'localhost', 8080)
        loop.run_until_complete(site.start())
        loop.run_forever()
    
    
    t = threading.Thread(target=run_server, args=(aiohttp_server(),))
    t.start()
    
    0 讨论(0)
  • 2021-01-18 02:34

    We must use app.make_handler handler in main thread, example:

    import asyncio
    import threading
    from aiohttp import web
    
    loop = asyncio.get_event_loop()
    
    
    def say_hello(request):
        return web.Response(text='Hello, world')
    
    
    app = web.Application(debug=True)
    app.add_routes([web.get('/', say_hello)])
    
    handler = app.make_handler()
    server = loop.create_server(handler, host='127.0.0.1', port=8080)
    
    
    def aiohttp_server():
        loop.run_until_complete(server)
        loop.run_forever()
    
    
    t = threading.Thread(target=aiohttp_server)
    t.start()
    
    0 讨论(0)
提交回复
热议问题