Gevent pywsgi server used with gunicorn? - flask

I have a flask app setup to use the gevent WSGIServer in my code. I am also running gunicorn on the command line to start the server.
Should I be using WSGI server in the code when also running with gunicorn? Currently looks like this:
from flask import Flask
from gevent.pywsgi import WSGIServer
application = Flask(__name__)
#application.route("/")
def hello():
return "hello"
if __name__ == '__main__':
port = int(os.environ.get('PORT', 5000))
WSGIServer(('', port), application).serve_forever()
On the command line I am running gunicorn like:
gunicorn -w 4 myapp:application
Do I need the WSGIServer in my code, or just run it as application.run() on the default flask server?

According to Standalone WSGI Containers, The gunicorn and gevent.pywsgi are both WSGI Containers, and the gunicorn only reconize the entry named application.
So the code below if __name__ == '__main__': is not useful anymore.
If you want to use gevent,you could do:
gunicorn -k gevent -w 4 myapp:application

Related

How to serve Flask app on waitress and socket.io using eventlet server simultaneously?

I'm using waitress server to deploy the flask app for production. I'm also using flask's socketio along with the eventlet server which requires its own app run.
Currently only serving app on waitress:
serve(app, host='0.0.0.0', port=8080)
How do I include the socket.run command for running the socket server?
socketio.run(app)
My code:
This snippet sets up server for the flask socketio on which it is to be run and in the if name part I serve the app on waitress if in prod mode.
app.py
import eventlet
async_mode = None
if async_mode is None:
try:
async_mode = 'eventlet'
except ImportError:
pass
if async_mode is None:
async_mode = 'threading'
print('async_mode is ' + async_mode)
if async_mode == 'eventlet':
eventlet.monkey_patch()
socketio = socketIO(app,cors_allowed_origins='*',async_mode=async_mode)
if __name__=='__main__':
if env_mode=='dev':
app.run(host='0.0.0.0', port=8080)
elif env_mode=='prod':
serve(app, host='0.0.0.0', port=8080)

File upload working when executing flask command but doesn't work using uwsgi

So I have this basic setup:
hello.py
from flask import Flask, request
from os import environ
app = Flask(__name__)
#app.route("/", methods=['POST'])
def hello():
return repr(request.files)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080)
wsgi.py
from hello import app
if __name__ == "__main__":
app.run()
Request is HTTP POST from nodejs.
Running flask command...
FLASK_APP="uwsgi.py" PYTHONUNBUFFERED=1 FLASK_ENV=development flask run --port=8080 --host=0.0.0.0
...output is:
ImmutableMultiDict([('file', <FileStorage: 'screenshot.png' ('image/png')>)])
Running uwsgi command...
venv/bin/uwsgi --http 0.0.0.0:8080 --plugin python --wsgi-file uwsgi.py --callable app --master --processes 4 --threads 2
..output is empty dict
ImmutableMultiDict([])

Heroku flask + socket.io 400 BAD REQUEST

Hello im trying to deploy my flask app on heroku. Im using flask_socketio module and socket.io in version 4.5(i didn't know how to initialize in 2.3.x version - io())
Here's my flask code:
from flask import Flask, render_template, url_for, redirect, session, request, jsonify
from flask_socketio import SocketIO
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
socketio = SocketIO(app)
#secret key etc...
...
#socketio.on('message')
def handle_msg(msg):
socketio.send('Syncing...')
if __name__ == '__main__':
socketio.run(app)
Here's my javascript:
...
export const socket = io();
socket.connect('https://proman-code-cool.herokuapp.com/');
function init() {
...
//live sync
socket.on('message', function(msg) {
console.log(msg);
boardsManager.reloadBoards(userId);
});
}
init();
And what i want is to make real-time sync to other users after adding something. And this is working locally but on heroku ive got all the time similar errors to:
When i've changed my Procfile to web: gunicorn -k eventlet main:app and with installed eventlet 0.30.2 i've got errors like class uri 'eventlet' invalid or not found. I can't find anywhere solution for that.
eventlet==0.30.2 in requirements.txt and python-3.8.13 in runtime.txt did the job!
Procfile: web: gunicorn --worker-class eventlet -w 1 main:app

code before app.run() can not be run in gunicorn+flask

#main.py
from flask import Flask
app = Flask(__name__)
if __name__ == '__main__':
print("before app run")
app.run() # , threaded=True host='0.0.0.0', debug=True, port=5000
Run gunicorn as follow:
gunicorn -b 0.0.0.0:8000 --preload main:app
the result will not print “before app unn”. How can i run the print code? if i don't want to place print outside of if __name__ == '__main__'
Gunicorn is not running the file, but importing it. That means that __name__ != "__main__" and your code never gets run.
Gunicorn then manually calls app.run() itself, after importing your file.
The solution is to make sure that your code is run at import time:
> cat main.py
from flask import Flask
app = Flask(__name__)
print "before main stanza"
if __name__ == "__main__":
print "in main stanza"
app.run()
And then running the app:
> gunicorn -b 0.0.0.0:8000 --preload main:app
before main stanza
[2017-06-07 08:33:15 +0100] [8865] [INFO] Starting gunicorn 19.7.1
[2017-06-07 08:33:15 +0100] [8865] [INFO] Listening at: http://0.0.0.0:8000 (8865)
...
Actually that will print before app run when you run this application with python main.py
It's not possible with Gunicorn though you can try before_first_request that will do the trick
#app.before_first_request
def execute_this():
print("before app run")

Django Gevent integration

How to integrate Gevent with Django framework, What settings has to be modified in the Settings.py and wsgi.py files for the integration.
I want to start gevent http server(port 8000) and gevent web socket server(port 9000) from the Django.
The easiest way is to use Gunicorn and tell it to use the gevent worker class. The Gunicorn docs are pretty good. For Django 1.4 or later the recommended way to start Gunicorn is simply to call the WSGI interface like so:
gunicorn --worker-class gevent wsgi:application
If you don't care about all the nice features of Gunicorn (like graceful restarts for no-downtime upgrades for example) you can use the gevent wsgi server directly. I do this myself to save some memory for non-critical websites that can be down for a little while during upgrades. This is my "run_gevent.py" file, it should be fairly easy to grok:
import gevent.monkey; gevent.monkey.patch_all()
import os, socket
from gevent.socket import socket as gsocket
from gevent.pywsgi import WSGIServer
from django.core.handlers.wsgi import WSGIHandler
script_dir = os.path.dirname(os.path.abspath(__file__))
pid_filename = os.path.join(script_dir, 'server.pid')
socket_filename = os.path.join(script_dir, 'server.sock')
pidfile = open(pid_filename, 'w')
pidfile.write(str(os.getpid()) + str('\n'))
pidfile.close()
server_socket = gsocket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
os.remove(socket_filename)
except OSError:
pass
server_socket.bind(socket_filename)
server_socket.listen(256)
os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings'
server = WSGIServer(listener = server_socket, application = WSGIHandler(), log = None)
server.serve_forever(stop_timeout = 3)