3

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.

user8865059
  • 71
  • 2
  • 13
  • Have you considered using `APScheduler` module? – ngShravil.py May 29 '20 at 04:00
  • Tried APScheduler and am able to make something work but SocketIO emit messages are delayed by ~25 seconds. The 'socketio.emit' command is now in backgroundTask() which is scheduled to run every 1 second with 'sched.add_job(backgroundTask,'interval',seconds=1)' – user8865059 May 30 '20 at 13:41
  • Could you update the same code in the OP? – ngShravil.py May 31 '20 at 05:55
  • 1
    Have you read the docs regarding running Flask-SocketIO on uWSGI? Your uwsgi start command is completely wrong, also you are forcing `async_mode='gevent'` which is not going to work with uWSGI. – Miguel Grinberg May 31 '20 at 09:16

2 Answers2

0

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.

Miguel Grinberg
  • 65,299
  • 14
  • 133
  • 152
  • I made the changes and am getting the DAMN ! worker 1 errors. Gevent is installed: gevent==20.5.2 gevent-websocket==0.10.1 python-socketio==4.6.0 uwsgi version is 2.0.18, on Ubuntu 18.0.4. I also removed firstFunction() and startBackgroundTask() so it is just flask-socketio – user8865059 Jun 01 '20 at 11:48
  • I chose to setup new EC2 t2.micro Ubuntu 18.04 instance to start fresh. I'm following Steps 1-3 from https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-uswgi-and-nginx-on-ubuntu-18-0 and then https://flask-socketio.readthedocs.io/en/latest/ for flask-SocketIO, and execute uWSGI as shown there. Right away I get `DAMN ! worker 1 (pid: 30699) died :( trying respawn ... worker respawning too fast !!! i have to sleep a bit (2 seconds)...` error. Is there something wrong with doing this on EC2 t2.micro instance? Appreciate any suggestions. – user8865059 Jun 02 '20 at 09:54
  • Did you fix the `async_mode` parameter? – Miguel Grinberg Jun 02 '20 at 10:10
  • yes I did from flask import Flask, render_template from flask_socketio import SocketIO app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) – user8865059 Jun 02 '20 at 10:16
  • Then look in the logs for other clues, not sure what else to suggest. Happy to take a look if you add the complete logs in your question. – Miguel Grinberg Jun 02 '20 at 17:44
  • Thanks for helping, see my answer above. – user8865059 Jun 03 '20 at 02:08
0

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.

user8865059
  • 71
  • 2
  • 13