DEV Community

DoriDoro
DoriDoro

Posted on

Python: try - except block

Generally it is good practice to keep the try and except blocks as small and specific as possible. This is because it helps you identify exactly which section of your code might be causing an exception, making debugging easier and ensuring that you don't inadvertently catch exceptions that you didn't intend to handle.

Applying this principle to the save method from article: In Django model: save an image with Pillow (PIL) library , you'll want to isolate the parts of the code that could potentially raise an exception and use try-except blocks specifically around those sections.

Here's a refactored save method with more focused try-except blocks:

from django.core.files.base import ContentFile from io import BytesIO from PIL import Image, ImageOps class Picture(models.Model): legend = models.CharField(max_length=100) photo = models.ImageField( upload_to="images/", blank=True, null=True, ) published = models.BooleanField(default=True) def __str__(self): return self.legend def save(self, *args, **kwargs): if self.photo: try: img = Image.open(self.photo) img.verify() except (IOError, SyntaxError) as e: raise ValueError(f"The uploaded file is not a valid image. -- {e}") # Reopen the image to reset the file pointer  try: img = Image.open(self.photo) except (IOError, SyntaxError) as e: raise ValueError(f"The uploaded file could not be reopened as an image. -- {e}") if img.mode in ("RGBA", "LA", "P"): img = img.convert("RGB") # Calculate new dimensions to maintain aspect ratio with a width of 800  new_width = 800 original_width, original_height = img.size new_height = int((new_width / original_width) * original_height) try: # Resize the image  img = img.resize((new_width, new_height), Image.LANCZOS) # Save the image as JPEG  temp_img = BytesIO() img.save(temp_img, format="JPEG", quality=70, optimize=True) temp_img.seek(0) # Change file extension to .jpg  original_name, _ = self.photo.name.lower().rsplit(".", 1) img_filename = f"{original_name}.jpg" # Save the BytesIO object to the ImageField with the new filename  self.photo.save(img_filename, ContentFile(temp_img.read()), save=False) except (IOError, SyntaxError) as e: raise ValueError(f"An error occurred while processing the image. -- {e}") super().save(*args, **kwargs) 
Enter fullscreen mode Exit fullscreen mode

Breakdown of Changes:

  1. Initial Image Verification:

    • Isolated the Image.open(self.photo) and img.verify() calls into their own try block to catch errors specific to loading and verifying the image.
  2. Image Reopen:

    • Isolated the Image.open(self.photo) again after verify() to handle potential errors specific to reopening the image.
  3. Image Processing (Resize, Convert to JPEG):

    • Isolated the resizing and conversion logic into its own try block to handle exceptions that could occur during image processing like resizing and saving as JPEG.

By doing this, if an error occurs, it’s clearer which section of code caused the exception. This makes your error handling both more precise and more robust.

Top comments (0)