Can I use gevent-socketio with Flask, running under Gunicorn, and still enjoy the nice exception printing, debugger, and reload capability that Flask offers? How would my gunicorn worker and WSGI app class look like?
3 Answers
I've got the exact same problem so I solved it by using watchdog.
pip install watchdog
together with this command:
watchmedo shell-command --patterns="*.py*;;*.less;*.css;*.js;*.txt;*.html" --recursive --command='kill -HUP `cat /tmp/gunicorn.pid` && echo "Reloading code" >> /tmp/gunicorn.log' ~/projectfolder
It requires (well, not really, but I point "Reloading code" into the same logfile so It's a nice thing to have) that you daemonize the gunicorn process, which I do like this:
gunicorn_config.py
workers = 2
worker_class = 'socketio.sgunicorn.GeventSocketIOWorker'
bind = '0.0.0.0:5000'
pidfile = '/tmp/gunicorn.pid'
debug = True
loglevel = 'debug'
errorlog = '/tmp/gunicorn.log'
daemon = True
Start the application:
gunicorn run:app -c gunicorn-config.py
View the log:
tail -f /tmp/gunicorn.log
From this point everything should be reloaded with each change in your project. It's a bit complicated but since gunicorn with a worker (or the built in socketio-server) doesn't have any reloading capabilities I had to do it like this.
It's a different approach compared to the decorator solution in the other answer but I like to keep the actual code clean from development specific solutions. Both accomplish the same thing so I guess you'll just have to pick the solution you like. :)
Oh, as an added bonus you get to use the production server in development which means both environments match each other.
I've been looking into this subject lately. I don't think you can easily use autoreload feature with Flask + gevent-socket.io + Gunicorn. Gunicorn is a production server that does not allow such features natively.
However, I found a nice solution for my development server : user SocketIOServer provided with the library and a Flask snippet for autoreload. Here is the startup script (runserver.py) :
from myapp import app
from gevent import monkey
from socketio.server import SocketIOServer
import werkzeug.serving
# necessary for autoreload (at least)
monkey.patch_all()
PORT = 5000
@werkzeug.serving.run_with_reloader
def runServer():
print 'Listening on %s...' % PORT
ws = SocketIOServer(('0.0.0.0', PORT), app, resource="socket.io", policy_server=False)
ws.serve_forever()
runServer()
This solution is inspired from : http://flask.pocoo.org/snippets/34/