user1315621
user1315621

Reputation: 3382

Start multiple vunicorn apps in python

I need to create a Python application that handles both API (fastAPI) and sockets (socketio). I can't find a way to start both the vunicorn applications in the same python script. Note that I can replace vunicorn with any other library that would allow me to fix this. Code:

import json

from fastapi import FastAPI
import socketio
import uvicorn


# create API app
app_api = FastAPI()

# create a Socket.IO server and wrap with a WSGI application
sio = socketio.Server(port=8001)
app_sio = socketio.WSGIApp(sio)


@app_api.get("/")
def read_root():
    return {"Hello": "World"}


@sio.on('*', namespace="/aws-iam")
def catch_all(event, sid, data):
    print(event, sid, data)

I am not sure how I can start both app_api and app_sio. I can't start both from the main thread because uvicorn.run(...) is blocking and only the first call would run. I tried to start them in two different threads but I got errors:

if __name__ == "__main__":

    def start_api():
        uvicorn.run("testing.mock_api:app_api", host='127.0.0.1', port=8000, reload=True, debug=True) #, workers=3)

    def start_sio():
         uvicorn.run("testing.mock_api:app_sio", host='127.0.0.1', port=8001, reload=True, debug=True) # , workers=3)


    from threading import Thread
    import time

    threads = [
        Thread(target=start_sio),
        Thread(target=start_api),
    ]
    for thread in threads:
        thread.start()
        
    time.sleep(999999999999)

With multiple thread I get the errors:

  File "/src/testing/mock_api.py", line 55, in start_api
    uvicorn.run("testing.mock_api:app_api", host='127.0.0.1', port=8000, reload=True, debug=True) #, workers=3)
  File "/usr/local/lib/python3.6/dist-packages/uvicorn/main.py", line 447, in run
    ChangeReload(config, target=server.run, sockets=[sock]).run()
  File "/usr/local/lib/python3.6/dist-packages/uvicorn/supervisors/basereload.py", line 43, in run
    self.startup()
  File "/usr/local/lib/python3.6/dist-packages/uvicorn/supervisors/basereload.py", line 62, in startup
    signal.signal(sig, self.signal_handler)
  File "/usr/lib/python3.6/signal.py", line 47, in signal
    handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
ValueError: signal only works in main thread

Upvotes: 0

Views: 1675

Answers (1)

Colin Le Nost
Colin Le Nost

Reputation: 490

Instead of running the two apps separatly, what about only running the FastAPI application & mount the socketio app on this one ?

To illustrate with an example from this github issue, you could do the following :

import socketio    
from fastapi import FastAPI
import uvicorn 
    
    
app = FastAPI()    
    
sio = socketio.AsyncServer(async_mode='asgi')    
socket_app = socketio.ASGIApp(sio)    
    

@sio.on('*', namespace="/aws-iam")
async def catch_all(event, sid, data):
    print(event, sid, data)


@app.get("/hello")
async def root():
    return {"message": "Hello World"}


app.mount('/', socket_app)


if __name__ == "__main__":
    uvicorn.run("main:app", reload=True, port=8080)

It includes switching socketio app to async too

Upvotes: 1

Related Questions