flask-socketio on uWSGI

Viewed 1669

I have this flask-socketio app

(venv) ubuntu@ip-172-31-18-21:~/code$ more app.py
from flask_socketio import SocketIO, send, emit
from flask import Flask, render_template, url_for, copy_current_request_context
from time import sleep
from threading import Thread, Event

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'

socketio = SocketIO(app, async_mode='gevent')

thread = Thread()
thread_stop_event = Event()

def firstFunction():
    print("*** First function")

def backgroundTask():
    while not thread_stop_event.isSet():
        socketio.emit('bg-socketio', {'data':'background-data'}, namespace='/', broadcast=True)
        socketio.sleep(2)

def startBackgroundTask():
    global thread

    if not thread.is_alive():
        thread = socketio.start_background_task(backgroundTask)

@app.route('/')
def main():
    return render_template('index.html', title='SocketIO')  

@socketio.on('connect_event', namespace='/')
def handle_message_client_connected(message):
    print("*** Client connected")
    emit('c-socketio', {'data':' you connected!'}, namespace='/') 

if __name__ == '__main__':
    firstFunction()
    startBackgroundTask()
    socketio.run(app, host='0.0.0.0', port=5000) 

I want firstFunction() and startBackgroundTask() to run whenever the app starts.

What is the best practice for running this on uWSGI? I've been trying to do this without any success, keep getting errors https://flask-socketio.readthedocs.io/en/latest/#uwsgi-web-server

Error: * running gevent loop engine [addr:0x5561d3f745a0] * DAMN ! worker 1 (pid: 13772) died :( trying respawn ... worker respawning too fast !!! i have to sleep a bit (2 seconds)... Respawned uWSGI worker 1 (new pid: 13773)

Also tried this

uwsgi --socket 0.0.0.0:5000 --protocol=http --enable-threads -w wsgi:app

(venv) ubuntu@ip-172-31-18-21:~/code$ more wsgi.py
from uapp import app

if __name__ == "__main__":
    app.run()

with uapp.py changed to

if __name__ == '__main__':
    firstFunction()
    startBackgroundTask()
    app.run(host='0.0.0.0', port=5000)

but this does not run firstFunction() or startBackgroundTask()

I'm pretty much stuck, looking for some suggestions.

2 Answers

The simple answer to your question is to change this:

if __name__ == '__main__':
    firstFunction()
    startBackgroundTask()
    app.run(host='0.0.0.0', port=5000)

to this:

firstFunction()
startBackgroundTask()

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

You have a couple other issues that you need to address, though.

The async_mode variable is set to gevent, but you are using uWSGI as a server. Either change it to gevent_uwsgi or remove it, so that it is automatically set at runtime for you.

The command to start a Flask-SocketIO app with uWSGI is shown in the documentation:

uwsgi --http :5000 --gevent 1000 --http-websockets --master --wsgi-file app.py --callable app

You need to also have gevent installed.

Was not working with gevent 20.5.2 which I installed with 'pip install gevent'. Changed to gevent==1.4.0 and now it uWSGI starts as expected.

Related