Reputation: 3382
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
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