I have one flask application 'merge.py'. From this I am calling two request and getting their response as:
from flask import Flask
from flask import request, jsonify
import json
import time
import requests
app = Flask(__name__)
#app.route('/check')
def check_working():
result_1 = requests.get('http://0.0.0.0:8080/hello').content
result_2 = requests.get('http://0.0.0.0:7000/bye').content
return "True"
if __name__=='__main__':
app.run(debug=True,host='128.7.7.10',threaded=True)
Right now when I am running the above file, both the request '/hello' and '/bye' running synchronously. How I can make them asynchronous with uwsgi. Suppose '/hello' is taking 10sec and '/bye' is taking 5sec, so total time it should take to execute is 10sec not 15sec. I want to collect the output of both the request. How I can achieve the asynchronous behavior here.
Thanks
Related
I am testing a simple slack command, which is supposed to return a response upon invocation and then start a new thread where it will calculate new response and post it back. However, it seems like there is no way to call jsonify inside the thread, because if do that, it throws : RuntimeError: Working outside of application context.
from flask import abort, Flask, jsonify, request
import requests
import json
from dateutil.parser import parse
from threading import Thread
def backgroundworker(somedata,response_url):
payload = jsonify(
response_type='in_channel',
text="test"
)
requests.post(response_url,data=json.dumps(payload))
#app.route('/appmethodaddress',methods=['POST','GET'])
def receptionist():
response_url = request.form.get("response_url")
somedata = {}
thr = Thread(target=backgroundworker, args=[somedata,response_url])
thr.start()
return jsonify(message= "working on your request")
Is there an easy way to call jsonify inside backgroundworker ?
If you have to make a json out of it, use json.dumps() method (https://kite.com/python/docs/json.dumps).
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
I'm trying to access the flask request object in a spawned Greenlet. Here's the code:
import gevent
from flask import Flask, request, render_template
app = Flask(__name__)
#app.route('/async')
def async():
gevent.spawn(do_async)
return 'OK'
def do_async():
html = render_template('async.html', args=request.args)
print html
When I hit the server, the first line in do_async() throws this error:
RuntimeError: working outside of request context
How do I allow do_sync() to "work outside of request context"?
Things I've tried:
Using with app.app_context(): in various places
Creating a new request object and passing it as a parameter to do_async() using
req = app.request_context(request.environ)
This throws the error
AttributeError: 'RequestContext' object has no attribute 'args'.
Copied the request object with the copy_current_request_context decorator. This works
but it then becomes blocking. The response isn't sent until do_async finishes even
though it's in a gevent thread.
Software versions:
python 2.7.5
uwsgi 2.0
gevent 1.0.1
flask 0.10.1
Edit:
Here's something I just noticed while I was trying to "unblock" the copy_current_request_context decorator. Here's the code:
import gevent
from flask import Flask, request, render_template
from flask import copy_current_request_context
app = Flask(__name__)
#app.route('/async')
def async():
#copy_current_request_context
def wrap_do_async():
do_async()
gevent.spawn(wrap_do_async)
return 'OK'
def do_async():
gevent.sleep(0.001) # Added to 'unblock' copy_current_request_context
html = render_template('async.html', args=request.args)
print html
Without the gevent.sleep(0.001) line in do_async(), the function works, but blocks (on the "real" do_async() code I'm simulating here it blocks for about 8 seconds). With the line, the function doesn't block but the request is now empty.
I am not able to successfully use Python Requests to call a second route in the same application using Flask. I know that its best practice to call the function directly, but I need it to call using the URL using requests. For example:
from flask import Flask
import requests
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!" # This works
#app.route("/myrequest")
def myrequest():
#r = requests.get('http://www.stackoverflow.com', timeout=5).text # This works, but is external
#r = hello() # This works, but need requests to work
r = requests.get('http://127.0.0.1:5000/', timeout=5).text # This does NOT work - requests.exceptions.Timeout
return r
if __name__ == "__main__":
app.run(debug=True, port=5000)
Your code assumes that your app can handle multiple requests at once: the initial request, plus the request that is generated while the initial is being handled.
If you are running the development server like app.run(), it runs in a single thread by default; therefore, it can only handle one request at a time.
Use app.run(threaded=True) to enable multiple threads in the development server.
As of Flask 1.0 the development server is threaded by default.
Flask is a single thread web server. But I want to make it won't block when handle some time consuming request.
For example:
from flask import Flask
import time
import sys
app = Flask(__name__)
#app.route("/")
def hello():
print "request"
sys.stdout.flush()
for _ in range(10000000):
for j in range(10000000):
i = 1
return "Hello World!"
if __name__ == "__main__":
app.run(debug=True)
I want when every client request to server, it always output "request" on console immediately. I have try gunicorn and run with gunicorn -k gevent -w 4 a:app but it still appears synchronous.
This snippet is a good starting point.
You also should look into Celery or RQ, they're the right thing to use for larger projects, more importantly they're not Flask-specific.
They also have Flask integration each, Flask-Celery and Flask-RQ.
I believe you are asking about something called "streaming". For Flask this can be accomplished using generator functions and the yield keyword.
Streaming is covered in more detail in the official Flask documentation, have a look here.