Hone logo
Hone
Problems

Asynchronous Image Processing with Celery

This challenge focuses on implementing asynchronous image processing tasks using Celery in Python. Celery is a powerful distributed task queue, and this exercise will demonstrate how to offload computationally intensive operations (like resizing images) from your main application thread, improving responsiveness and scalability. You'll be creating a Celery app, defining a task, and configuring it to run asynchronously.

Problem Description

You are tasked with building a simple image resizing service using Celery. The service should accept an image file path and a desired width as input. The task should resize the image to the specified width, maintaining the aspect ratio, and save the resized image to a new file named "resized_[original_filename]". The original image file should remain unchanged. The task should return the path to the newly created resized image.

Key Requirements:

  • Celery App: Create a Celery application instance.
  • Task Definition: Define a Celery task named resize_image that takes the image file path and desired width as arguments.
  • Image Resizing: Within the task, use the Pillow (PIL) library to resize the image. Ensure the aspect ratio is preserved.
  • File Saving: Save the resized image with the prefix "resized_" before the original filename.
  • Return Value: The task should return the path to the newly created resized image file.
  • Asynchronous Execution: The task should be executed asynchronously.
  • Error Handling: Implement basic error handling to catch potential exceptions during image processing (e.g., file not found, invalid image format). If an error occurs, the task should return None.

Expected Behavior:

When the resize_image task is called, it should:

  1. Read the image from the provided file path.
  2. Resize the image to the specified width, preserving aspect ratio.
  3. Save the resized image with the "resized_" prefix.
  4. Return the path to the resized image.
  5. If any error occurs during the process, return None.

Examples

Example 1:

Input: image_path = "path/to/my_image.jpg", width = 200
Output: "path/to/resized_my_image.jpg"
Explanation: The task resizes "my_image.jpg" to a width of 200 pixels, preserving the aspect ratio, and saves it as "resized_my_image.jpg". The function returns the path to the new file.

Example 2:

Input: image_path = "path/to/nonexistent_image.png", width = 300
Output: None
Explanation: The file "nonexistent_image.png" does not exist. The task catches the FileNotFoundError and returns None.

Example 3:

Input: image_path = "path/to/corrupted_image.bmp", width = 150
Output: None
Explanation: The image "corrupted_image.bmp" is corrupted and cannot be opened by Pillow. The task catches the IOError and returns None.

Constraints

  • Image Formats: The task should handle common image formats like JPG, PNG, and BMP.
  • File Paths: Assume the provided file paths are valid strings.
  • Width: The width parameter will be a positive integer.
  • Pillow Dependency: You are expected to use the Pillow (PIL) library for image processing. Ensure it's installed (pip install Pillow).
  • Celery Configuration: For simplicity, you can use an in-memory message broker (Redis or RabbitMQ are recommended for production). A basic configuration is sufficient for this exercise.
  • Task Execution Time: The task execution time is not a primary concern for this exercise, but avoid inefficient image processing techniques.

Notes

  • Remember to initialize and configure your Celery app correctly.
  • Consider using try...except blocks to handle potential errors during image processing.
  • The aspect ratio should be maintained during resizing. Pillow's thumbnail method can be helpful for this.
  • The task should be idempotent – running it multiple times with the same input should produce the same output (resized image).
  • This challenge focuses on the core task definition and execution. You don't need to build a full-fledged web application or API. Focus on the Celery task itself.
  • You'll need to start the Celery worker process separately to execute the tasks. The instructions for doing so will depend on your Celery configuration.
Loading editor...
python