当修饰函数加载截断的映像时,Diskcache模块无法缓存

2024-04-18 15:34:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试缓存一个使用PIL.Image.open加载图像的函数(我也尝试过mpimg.imread)。一些图像被截断;我得到OSError: image file is truncated (0 bytes not processed)。我已尝试ImageFile.LOAD_TRUNCATED_IMAGES = True防止引发异常。这是可行的,但diskcache模块的缓存没有显示任何效果

下面是一个示例代码段,它显示了在文件夹中存在截断图像时的这种行为:

import diskcache
import os
from PIL import Image

cache = diskcache.Cache(directory="/tmp/cache")
@cache.memoize(expire=1000)
def load_images(path):
    return [Image.open(os.path.join(path, f)) for f in os.listdir(path)]

load_images("/path/to/image/folder")

也不可能从修饰函数捕获异常。我这样试过:

cache = diskcache.Cache(directory="/tmp/cache")
@cache.memoize(expire=1000)
def load_images(path):
    
    def load_image(filename):
        try:
            return Image.open(os.path.join(path, filename))
        except OSError:
            return None
        
    return list(map(load_image, os.listdir(path)))

但函数仍然出错;这就是错误:

---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
/tmp/ipykernel_41351/160153895.py in <module>
     11     return [Image.open(os.path.join(path, f)) for f in os.listdir(path)]
     12 
---> 13 x = load_images("/path/to/image/folder")

~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/diskcache/core.py in wrapper(*args, **kwargs)
   1889                     result = func(*args, **kwargs)
   1890                     if expire is None or expire > 0:
-> 1891                         self.set(key, result, expire, tag=tag, retry=True)
   1892 
   1893                 return result

~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/diskcache/core.py in set(self, key, value, expire, read, tag, retry)
    773         db_key, raw = self._disk.put(key)
    774         expire_time = None if expire is None else now + expire
--> 775         size, mode, filename, db_value = self._disk.store(value, read, key=key)
    776         columns = (expire_time, tag, size, mode, filename, db_value)
    777 

~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/diskcache/core.py in store(self, value, read, key)
    239             return size, MODE_BINARY, filename, None
    240         else:
--> 241             result = pickle.dumps(value, protocol=self.pickle_protocol)
    242 
    243             if len(result) < min_file_size:

~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/PIL/Image.py in __getstate__(self)
    694 
    695     def __getstate__(self):
--> 696         return [self.info, self.mode, self.size, self.getpalette(), self.tobytes()]
    697 
    698     def __setstate__(self, state):

~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/PIL/Image.py in getpalette(self)
   1358         """
   1359 
-> 1360         self.load()
   1361         try:
   1362             return list(self.im.getpalette())

~/anaconda3/envs/image-service-v1/lib/python3.9/site-packages/PIL/ImageFile.py in load(self)
    247                                     break
    248                                 else:
--> 249                                     raise OSError(
    250                                         "image file is truncated "
    251                                         f"({len(b)} bytes not processed)"

OSError: image file is truncated (0 bytes not processed)

我觉得很奇怪,加载图像的问题导致缓存无效。你知道如何解决这个问题吗?”。也许diskcache的维护者甚至会注意到这个标签

顺便说一句,用mpimg.imread加载会产生此错误TypeError: No loop matching the specified signature and casting was found for ufunc true_divide

编辑

我将调试打印文件放入matplotlib.image中,放入该块中的_pil_png_to_float_array。当转换为numpy数组时,损坏的图像没有形状

    if mode == "RGB":  # RGB.
        print(np.array(pil_png).shape)  # prints `()`
        return np.divide(pil_png, 2**8 - 1, dtype=np.float32)