Making an asynchronous task in Flask
I would use Celery to handle the asynchronous task for you. You'll need to install a broker to serve as your task queue (RabbitMQ and Redis are recommended).
app.py
:
from flask import Flask
from celery import Celery
broker_url = 'amqp://guest@localhost' # Broker URL for RabbitMQ task queue
app = Flask(__name__)
celery = Celery(app.name, broker=broker_url)
celery.config_from_object('celeryconfig') # Your celery configurations in a celeryconfig.py
@celery.task(bind=True)
def some_long_task(self, x, y):
# Do some long task
...
@app.route('/render/<id>', methods=['POST'])
def render_script(id=None):
...
data = json.loads(request.data)
text_list = data.get('text_list')
final_file = audio_class.render_audio(data=text_list)
some_long_task.delay(x, y) # Call your async task and pass whatever necessary variables
return Response(
mimetype='application/json',
status=200
)
Run your Flask app, and start another process to run your celery worker.
$ celery worker -A app.celery --loglevel=debug
I would also refer to Miguel Gringberg's write up for a more in depth guide to using Celery with Flask.
Is there a way to make flask asynchronous
Flask is based WSGI which is an API standard for connecting Python Web frameworks to Web servers.
And WSGI is a synchronous and blocking API.
If you are using flask render_template, like this :
@app.route('/home', methods=['GET'])
def hello(name=None):
return render_template('hello.html', name=name)
You can add a time.sleep() to make if wait before rendering the template.
But this is not a good practice
import time
@app.route('/home', methods=['GET'])
def hello(name=None):
time.sleep(30) #wait 30seconds
return render_template('hello.html', name=name)
But if you want to use it with a frontend in javascript, you should handle it on the client side.
And if you want to know about async tasks on flask you can take a look on Celery and this post.
Synchronous api tasks on Python Flask
First, depending on what you mean by "async", yes, you can make HTTP requests to a Flask app that arranges to do work asynchronously. That's what tasks queues like celery and Rq are for. There's a good walk-through of using Rq in chapter 22 of the Flask Mega Tutorial.
Second, if you only have a single process, single thread web server, then yes, requests are handled sequentially. In practice, though, you'll deploy behind something like uwsgi
or gunicorn
, which manage multiple processes running your app.
How to send asynchronous request using flask to an endpoint with small timeout session?
If you are trying to have a async task in request, you have to decide whether you want the result/progress or not.
- You don't care about the result of the task or if there where any errors while processing the task. You can just process this in a Thread and forget about the result.
- If you just want to know about success/fail for the task. You can store the state of the task in Database and query it when needed.
- If you want progress of the tasks like (20% done ... 40% done). You have to use something more sophisticated like celery, rabbitMQ.
For you i think option #2 fits better. You can create a simple table GitTasks.
GitTasks
------------------------
Id(PK) | Status | Result
------------------------
1 |Processing| -
2 | Done | <your result>
3 | Error | <error details>
You have to create a simple Threaded object in python to processing.
import threading
class AsyncGitTask(threading.Thread):
def __init__(self, task_id, params):
self.task_id = task_id
self.params = params
def run():
## Do processing
## store the result in table for id = self.task_id
You have to create another endpoint to query the status of you task.
@app.route('/TaskStatus/<int:task_id>')
def task_status(task_id):
## query GitTask table and accordingly return data
Now that we have build all the components we have to put them together in your main request.
from Flask import url_for
@app.route('/', methods=['POST', 'GET'])
def handle_data():
.....
## create a new row in GitTasks table, and use its PK(id) as task_id
task_id = create_new_task_row()
async_task = AsyncGitTask(task_id=task_id, params=params)
async_task.start()
task_status_url = url_for('task_status', task_id=task_id)
## This is request you can return text saying
## that "Your task is being processed. To see the progress
## go to <task_status_url>"
Related Topics
What Is the Recommended Way of Allocating Memory for a Typed Memory View
What Exactly Is Contained Within a Obj._Closure_
How to Use Pip to Install a Package from a Private Github Repository
Subprocess.Popen() Error (No Such File or Directory) When Calling Command with Arguments as a String
Python Beautifulsoup Extract Text Between Element
Why Are Str.Count('') and Len(Str) Giving Different Output
How to Read Hdf5 Files in Python
Update Row Values Where Certain Condition Is Met in Pandas
How to Do Assignments in a List Comprehension
Setting Stacksize in a Python Script
In Python What Is a Global Statement
Generating Matplotlib Graphs Without a Running X Server
Type Hint for a Function That Returns Only a Specific Set of Values
Ssl.Sslerror: [Ssl: Certificate_Verify_Failed] Certificate Verify Failed (_Ssl.C:749)
Compulsory Usage of If _Name_=="_Main_" in Windows While Using Multiprocessing