Flask
asynchronous programming
Python
web development
task scheduling

Making an asynchronous task in Flask

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Flask is a lightweight WSGI web application framework in Python that's designed for simplicity. However, because Flask's default setup operates on a single request-response cycle, long-running tasks can block your application and degrade user experience. Asynchronous tasks allow you to defer these operations, enabling your application to remain responsive.

Understanding Asynchronous Tasks

Asynchronous tasks involve executing operations outside of the main thread, preventing tasks from blocking further operations. In web applications, these tasks are particularly useful for operations like sending emails, processing uploads, or handling long-running calculations.

Implementing Asynchronous Tasks with Celery

Celery is a popular asynchronous task queue that integrates well with Flask to handle asynchronous tasks. Here's a step-by-step guide on setting up Celery with Flask:

Prerequisites

  1. Python & Flask: Make sure Python and Flask are installed.
  2. Celery: Install Celery using pip.
bash
   pip install celery
  1. Broker: Celery requires a broker to intermediate between workers and tasks. RabbitMQ or Redis are common choices. Here's how you can install Redis:
bash
1   # On Debian-based systems:
2   sudo apt install redis-server
3
4   # On macOS (using Homebrew):
5   brew install redis
  1. Flask-Session (Optional): To handle sessions across distributed workers, consider using Flask-Session.

Setting Up Flask and Celery

Flask Application Structure

Create a basic Flask application:

python
1# app.py
2from flask import Flask
3
4app = Flask(__name__)
5
6@app.route('/')
7def home():
8    return "Welcome to Flask with Celery"
9
10if __name__ == '__main__':
11    app.run(debug=True)

Configuring Celery

Integration of Flask with Celery involves creating a separate Celery object and configuring it using Flask's configuration.

python
1# celery_app.py
2from celery import Celery
3
4def make_celery(app):
5    # Define the Celery object
6    celery = Celery(
7        app.import_name,
8        broker=app.config['CELERY_BROKER_URL']
9    )
10    
11    # Optional: To have the results backend
12    celery.conf.update(app.config)
13    
14    class ContextTask(celery.Task):
15        def __call__(self, *args, **kwargs):
16            with app.app_context():
17                return self.run(*args, **kwargs)
18    
19    celery.Task = ContextTask
20    return celery

Configuring Flask Application

Update your Flask configuration to include Celery settings:

python
1# config.py
2class Config:
3    CELERY_BROKER_URL = 'redis://localhost:6379/0'
4    CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'

Apply this configuration in your Flask application:

python
1# app.py
2from config import Config
3app.config.from_object(Config)
4
5celery = make_celery(app)

Creating and Running Asynchronous Tasks

Define asynchronous tasks using the @celery.task decorator:

python
1# tasks.py
2from celery_app import celery
3
4@celery.task
5def add(x, y):
6    return x + y

Invoking Asynchronous Tasks

Within your Flask routes, invoke the asynchronous task:

python
1@app.route('/add/<int:a>/<int:b>')
2def add_numbers(a, b):
3    job = add.delay(a, b)
4    return f'Task has been submitted, task ID: {job.id}'

Running the Celery Worker

To process tasks, you need to run a Celery worker:

bash
celery -A celery_app.celery worker --loglevel=info

Flask and Celery In Practice

Here's a summary of the process involved in implementing asynchronous tasks in Flask with Celery:

StepDescription
1Install Flask and Celery using pip.
2Set up a broker like Redis or RabbitMQ.
3Establish a Flask application with the needed config.
4Define and configure a Celery object in a separate module.
5Use the @celery.task decorator to define asynchronous tasks.
6Run a Celery worker to process tasks.
7Call tasks using .delay() within Flask routes.

Advanced Topics

Task Monitoring

Celery offers several options for monitoring tasks:

  • Flower: A real-time web-based monitoring tool for Celery.
  • CLI Commands: Celery provides commands to list tasks, status, and to inspect running threads.

Retries and Error Handling

Celery supports automatic retries and error handling, allowing you to specify the number of retries and intervals between them:

python
1@celery.task(bind=True, max_retries=3)
2def resilient_task(self, x):
3    try:
4        # Some operation
5        return x * 2
6    except Exception as e:
7        self.retry(exc=e, countdown=60)

Chaining Tasks

Celery enables task chaining, allowing sequential task execution:

python
from celery import chain

result = chain(add.s(2, 3) | add.s(5)).apply_async()

Conclusion

Implementing asynchronous tasks in Flask using Celery significantly improves application responsiveness by offloading long-running processes. This strategy is vital for applications requiring scalability, reliability, and performance efficiency. With Celery, you can easily integrate task scheduling, retries, error handling, and monitoring to build robust web applications.


Course illustration
Course illustration

All Rights Reserved.