Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run an aiohttp server in a thread?

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

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)])
    web.run_app(app)


t = threading.Thread(target=aiohttp_server)
t.start()

How to run a aiohttp server in thread?

like image 248
bux Avatar asked Jul 31 '18 09:07

bux


3 Answers

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())

like image 74
Heron Rossi Avatar answered Sep 28 '22 18:09

Heron Rossi


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()
like image 7
Sraw Avatar answered Oct 09 '22 11:10

Sraw


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()
like image 2
bux Avatar answered Oct 09 '22 12:10

bux