django-versatileimagefield icon indicating copy to clipboard operation
django-versatileimagefield copied to clipboard

Stdout call creates blank error in log

Open lgellert opened this issue 7 years ago • 1 comments

Just spent an hour or so tracing down a blank wsgi:error line that kept appearing in my live server logs. It was caused by the VersatileImageFieldWarmer.warm() method which is writing a new line character to stdout. I have a post_save receiver setup that automatically warms images when the model is saved, per docs on Auto-creating sets of images on post_save.

Towards the bottom VersatileImageFieldWarmer.warm() does this:

if a * b == total:
      stdout.write('\n')

So for now I monkey patched my version with:


def patched_warm_method(self):
    """
    NOTE - this is a MONKEY PATCH to fix the VersatileImageFieldWarmer.warm() method from using
    stdout specifically where it does stdout.write('\n')
    This keeps blank error lines out of the log, which are confusing!

    Returns a 2-tuple:
    [0]: Number of images successfully pre-warmed
    [1]: A list of paths on the storage class associated with the
         VersatileImageField field being processed by `self` of
         files that could not be successfully seeded.
    """
    num_images_pre_warmed = 0
    failed_to_create_image_path_list = []
    total = self.queryset.count() * len(self.size_key_list)
    for a, instance in enumerate(self.queryset, start=1):
        for b, size_key in enumerate(self.size_key_list, start=1):
            success, url_or_filepath = self._prewarm_versatileimagefield(
                size_key,
                reduce(getattr, self.image_attr.split("."), instance)
            )
            if success is True:
                num_images_pre_warmed += 1
            else:
                failed_to_create_image_path_list.append(url_or_filepath)

    return (num_images_pre_warmed, failed_to_create_image_path_list)

And then you can use the patched version like so:

   # MONKEY PATCH the warm method (see notes on patched_warm_method)
    VersatileImageFieldWarmer.warm = patched_warm_method
    img_warmer = VersatileImageFieldWarmer(
        instance_or_queryset=instance,
        rendition_key_set='image_field',
        image_attr='image_field',
    )
    num_created, failed_to_create = img_warmer.warm()

lgellert avatar Jan 10 '18 05:01 lgellert

As alternative you may use patch context manager from unittest to change stdout to devnull:

with open(os.devnull, "w") as f:
    with patch("versatileimagefield.image_warmer.stdout", f):
        Warmer(...).warm()

But it would be nice to pass some optional argument to warm, so as not to output anything to stdout

GreyZmeem avatar Jan 08 '19 09:01 GreyZmeem