Flask Lazy loding with waitress - python

im was working with my flask app on my development server, but now i want to move that same application to a production enviroment. The thing is that when i was running that same application with flask run, i got the lazy loading message so i move to waitress in order to avoid this behaviour. When i use waitress the message dissapears but the behaviour is the same. The app is slow at the first request and then works properly.
Bellow you can find part of my code :
import flask
import io
import string
import time
import os
from flask import Flask, jsonify, request
import load_model
import prepare_image
from flask_cors import CORS
from waitress import serve
from paste.translogger import TransLogger
app = Flask(__name__)
#control archivo mayor a 16 mb
app.config['MAX_CONTENT_LENGTH'] = 4096 * 4096
cors = CORS(app, resources={r"/*": {"origins": "*"}})
#app.route('/predict', methods=['POST'])
blablabla
if __name__ == '__main__':
serve(TransLogger(app, setup_console_handler=False),port=5000)
Thanks in advance
when the app is served with weitress the lazy loading mode doesnt seem to disappear.

Related

Flask Rate Limiter not working with flask-restful

I believe I have the same problem as described here: Flask-Limiter does not work with Flask-Restful API-based application. But I still can't get it to work. Here's my problem:
I have an app.py where I import all my REST-API endpoints. I use flask-RESTful resources as described in this guide: https://flask-restful.readthedocs.io/en/latest/quickstart.html
I use the "Flask-Limiter" library for rate limiting: https://flask-limiter.readthedocs.io/en/stable/. The rate-limiter gets instantiated in a separate file, not inside app.py because this would create circular references between app.py and the REST-API endpoints. I think this could be the cause of my problem.
This is the rate-limiter file (located in: /controller/helpers/rate_limiter.py)
from flask import current_app
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
current_app,
key_func=get_remote_address
)
This is the app.py file (located in: /):
from flask import Flask
from flask_restful import Api
from controller.actions.my_endpoint import MyEndpoint
flask_app = Flask(__name__)
api = Api(flask_app)
api.add_resource(MyEndpoint, '/endpoint')
flask_app.run(debug=True, use_reloader=True, host='0.0.0.0', port=8000)
And finally this is an example of an endpoint (located in: /controller/actions/my_endpoint):
from flask_restful import reqparse, Resource
from controller.helpers.rate_limiter import limiter
class MyEndpoint(Resource):
decorators = [limiter.limit("1/minute", methods=["POST"])]
def __init__(self):
self.parser = reqparse.RequestParser()
self.parser.add_argument(
"someData", type=int, nullable=False, required=True)
def post(self):
data = self.parser.parse_args(strict=True)
someData = data.someData
return "Got your message {0}".format(someData), 200
I would expect that after the first request I would get response 429 because the rate limit of 1/minute is reached but it doesn't do that.
However, when I instantiate the limiter inside app.py and set a default rate-limit, it works (getting that error 429):
from flask import Flask
from flask_restful import Api
from controller.db_actions.my_endpoint import MyEndpoint
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
flask_app = Flask(__name__)
limiter = Limiter(
flask_app,
key_func=get_remote_address,
default_limits=["1 per minute"]
)
api = Api(flask_app)
api.add_resource(MyEndpoint, '/endpoint')
flask_app.run(debug=True, use_reloader=True, host='0.0.0.0', port=8000)
Question: I think I'm doing something wrong with instantiating the limiter. What is it? :)

ECONNRESET Error response getting from flask python

I'm not getting the proper response for this particular API. Also , In actual implementation, I'm getting the proper 200 jsonify response when all things are running fine but if their is any exception and If I want to send back the response with 500 status code : the postman say Could not get response : "Error: read ECONNRESET" and in my console it display as "127.0.0.1 - - [04/Aug/2020 23:57:22] "←[37mPOST /hi HTTP/1.1←[0m" 500 -"
can someone please tell me , where I'm going wrong ?
from flask import Flask, jsonify, request, abort, json
from werkzeug.utils import secure_filename
from werkzeug.exceptions import HTTPException
from flask_cors import CORS, cross_origin
import traceback
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#app.route("/hi", methods=['POST'])
def hi():
val = 500
dict_json = {"messgae": "lets work it out {} ".format(val)}
return jsonify(dict_json), val
I had this problem today and found that it seems to be an issue with the flask server. It works fine usually however sometimes requests with postman would time out with the error you've mentioned.
Can you try hosting it instead with waitress?
To do that add this to the top of your file
from waitress import serve
then instead of running app.run() you run serve(app, host='localhost', port=7777)
oh, and for waitress to work you will of course need to run pip install waitress first!

seperate python flask files into multiple files

I've already read much about it on stack overflow but now I'm struggling with an issue and don't know how to fix it.
My main.py looks like the following:
from flask import Flask, jsonify, request
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
from flask_cors import CORS
app = Flask(__name__)
# connect to LiTags database
app.config["MONGO_URI"] = "mongodb://localhost:27017/LiTags"
mongo = PyMongo(app)
CORS(app)
if __name__ == "__main__":
app.run(debug=True)
then I seperated some database requests (MongoDB) in another file(requests.py). I know that it's not necessary right now because there are not that much requests right now but there will be more after I fixed this problem.
So this is my requests.py:
from main import app, mongo
from flask import Flask, jsonify, request, Blueprint
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
#app.route("/", methods=["GET"])
def getProjects():
result = []
projects = mongo.db.literature
for field in projects.find():
result.append(
{"_id": str(field["_id"]), "project_name": field["project_name"]})
return jsonify(result)
this is generally my frontend (ReactJS) request to flask:
// get project names from the backend
getProjects() {
axios.get(`http://127.0.0.1:5000/`)
.then(res => {
this.setState({ projects: res.data });
})
}
before I seperated the requests in requests.py from the main.py my program worked but now I get an error in the inspect tool in the browser which says:
"GET http://127.0.0.1:5000/ 404 (NOT FOUND)
Error: Request failed with status code 404
at createError (createError.js:17)
at settle (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:63)"
In main.py you would have to import requests.py
from requests import *
because main.py doesn't know that you have code in other file .
But there can be problem with circular imports - main.py has to import requests.py but requests.py aready imports main.py and it makes problem.
You may have to split main in two files:
main.py - which doesn't need code from reuqests so it doesn't have to import it
from flask import Flask, jsonify, request
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
from flask_cors import CORS
app = Flask(__name__)
# connect to LiTags database
app.config["MONGO_URI"] = "mongodb://localhost:27017/LiTags"
mongo = PyMongo(app)
CORS(app)
run.py - which needs code from requests (but requests doesn't import it)
from main import *
#from main import app
from requests import *
#from models import *
#from views import *
#from admin import *
if __name__ == "__main__":
app.run(debug=True)
and now you would have to use run.py instead of main.py to start server.
python run.py
BTW: most people and tutorials/documentations use name views.py instead of requests.py for file with code which use #app.route. Eventaully I would use name api.py because these views return JSON data like in many APIs.

How to check my metrics using prometheus_flask_exporter lib

I want to keep track of metrics in my flask application using the lib prometheus_flask_exporter.
For what i could understand this lib already tracks default metrics in the /metrics endpoint.
But when i try to access the http://localhost:5000/metrics I get 404 Not Found.
So i tried to set a histogram metric on the user_list, but i get the same 404 not Found when i try to access the http://localhost:5000/metrics
init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flasgger import Swagger
from flask_caching import Cache
from prometheus_flask_exporter import PrometheusMetrics
app = Flask(__name__)
app.debug = True
app.config.from_object('dev_maintenance.yaml_config_loader')
cache = Cache(app)
db = SQLAlchemy(app)
swagger = Swagger(app)
metrics = PrometheusMetrics(app)
import dev_maintenance.mesos_callback
import dev_maintenance.db_model
import dev_maintenance.active_directory
import dev_maintenance.user_list
import dev_maintenance.audit
import dev_maintenance.machines
import dev_maintenance.yaml_config_loader
import dev_maintenance.roles
import dev_maintenance.user_details
if __name__ == '__main__':
app.run(debug=True)
user_list.py
from dev_maintenance import app
from flask import jsonify, request
from flask_simpleldap import LDAP
from flask_jwt_extended import jwt_required
from dev_maintenance import metrics
ldap = LDAP(app)
#app.route('/api/user', methods=['GET'])
#metrics.do_not_track()
#metrics.histogram('requests_by_status_and_path', 'Request latencies by status and path',
labels={'status': lambda r: r.status_code, 'path': lambda: request.path})
def user_list():
user_list = []
users = ldap.get_group_members('ship_crew')
for user in users:
user_list.append(str(user, encoding='utf-8').split(",")[0].split("=")[1])
return jsonify(user_list)
Do i need to create a /metrics route? Because in the git documentation does not say anything about that, so i suppose this is already set behind the scenes.
Instead of "app.run(debug=True)" use "app.run(debug=False)". debug=True was breaking things.
From:https://github.com/rycus86/prometheus_flask_exporter/blob/master/README.md
Please note, that changes being live-reloaded, when running the Flask app with debug=True, are not going to be reflected in the metrics. See https://github.com/rycus86/prometheus_flask_exporter/issues/4 for more details.
Alternatively - since version 0.5.1 - if you set the DEBUG_METRICS environment variable, you will get metrics for the latest reloaded code. These will be exported on the main Flask app. Serving the metrics on a different port is not going to work most probably - e.g. PrometheusMetrics.start_http_server(..) is not expected to work.

No response from a Flask application using Apache server

I have created a flask application and am hosting it on a Ubuntu server. I know that my apache config is correct since I am able serve the example flask application. However, this one seems to be giving me trouble. The code is below:
from flask import Flask, render_template, request, url_for
import pickle
import engine
import config
# Initialize the Flask application
app = Flask(__name__)
model = pickle.load(open(config.MODEL_PATH, "rb"))
collection = engine.Collection(config.DATABASE_PATH)
search_engine = engine.SearchEngine(model, collection)
#app.route('/')
def form():
return render_template('index.html')
#app.route('/search/', methods=['POST'])
def search():
query = request.form['query']
results = search_engine.query(query)
return render_template('form_action.html', query=query, results=results)
#app.route('/retrieve/<int:item_number>', methods=['GET'])
def retrieve(item_number):
item = engine.Product(item_number, collection.open_document(str(item_number)))
return render_template('document.html', item=item)
if __name__ == '__main__':
app.run()
When running the file directly through the python interpreter, it works fine and I can access. However, when starting through apache and wsgi, I get no response from the server. It just hangs when making a request and nothing is available on the logs.
I suspect that my issue may have something to do with the three objects I initialize at the beginning of the program. Perhaps it gets stuck running those?
Update: I have tried commenting out certain parts of the code to see what is causing it to stall. Tracing it out to the engine module, importing NearestNeighbors seems to be causing the issue.
import sqlite3
import config
from sklearn.neighbors import NearestNeighbors
from preprocessor import preprocess_document
from collections import namedtuple

Categories

Resources