You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Kaggle竞赛Zip文件读取PIL图片时遇AttributeError错误求助

问题:从Zip文件读取图片时出现AttributeError及numpy转换异常

正在练习Kaggle的「Dogs vs. Cats Redux: Kernels Edition」竞赛,尝试用以下Python代码从训练集Zip文件读取图片:

def get_files_names(zip_file_path):
    with ZipFile(zip_file_path) as myzip:
        return myzip.namelist()


def get_image(zip_path, image_name):
    with ZipFile(zip_path) as myzip:
        with myzip.open(image_name) as myfile:
            img = Image.open(myfile)

    return img

names = get_files_names(train_file_path)

img = get_image(train_file_path, names[1])

img.show()

调用img.show()时出现如下错误:

Traceback (most recent call last):
  File "/cats_vs_dogs/unrelated_file.py", line 46, in <module>
    img.show()
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/Image.py", line 2205, in show
    _show(self, title=title, command=command)
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/Image.py", line 3167, in _show
    _showxv(image, **options)
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/Image.py", line 3181, in _showxv
    ImageShow.show(image, title, **options)
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/ImageShow.py", line 56, in show
    if viewer.show(image, title=title, **options):
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/ImageShow.py", line 81, in show
    return self.show_image(image, **options)
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/ImageShow.py", line 107, in show_image
    return self.show_file(self.save_image(image), **options)
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/ImageShow.py", line 103, in save_image
    return image._dump(format=self.get_format(image), **self.options)
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/Image.py", line 636, in _dump
    self.load()
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/ImageFile.py", line 247, in load
    s = read(self.decodermaxblock)
  File "/Users/user/.pyenv/versions/3.7.8-thesis/lib/python3.7/site-packages/PIL/JpegImagePlugin.py", line 400, in load_read
    s = self.fp.read(read_bytes)
  File "/Users/user/.pyenv/versions/3.7.8/lib/python3.7/zipfile.py", line 930, in read
    data = self._read1(n)
  File "/Users/user/.pyenv/versions/3.7.8/lib/python3.7/zipfile.py", line 998, in _read1
    data += self._read2(n - len(data))
  File "/Users/user/.pyenv/versions/3.7.8/lib/python3.7/zipfile.py", line 1030, in _read2
    data = self._fileobj.read(n)
  File "/Users/user/.pyenv/versions/3.7.8/lib/python3.7/zipfile.py", line 753, in read
    self._file.seek(self._pos)
AttributeError: 'NoneType' object has no attribute 'seek'

将图片提取到Mac本地Finder后可正常查看,尝试将RGB图片转为numpy数组np.array(img)时也出现异常,请问哪里操作出错了?


解决方法

问题根源在于PIL的Image.open()采用延迟加载机制:它不会立即读取文件中的图片数据,而是在调用show()、np.array()或其他需要访问像素数据的方法时才会去读取。但你的代码中,当退出with myzip.open(image_name) as myfile:的上下文管理器后,myfile这个文件对象已经被关闭,后续再尝试读取数据时,就会因文件对象失效而抛出AttributeError。

你可以通过以下两种方式解决:

方法一:在文件对象有效时预加载图片数据

修改get_image函数,在myfile打开的上下文内调用img.load(),将图片数据提前加载到内存中:

def get_image(zip_path, image_name):
    with ZipFile(zip_path) as myzip:
        with myzip.open(image_name) as myfile:
            img = Image.open(myfile)
            img.load()  # 立即加载图片内容到内存,脱离文件对象也能访问
    return img

方法二:读取二进制数据到内存后再打开

直接读取Zip内图片的二进制内容,用BytesIO包装成内存文件对象,再用Image.open()打开:

from io import BytesIO

def get_image(zip_path, image_name):
    with ZipFile(zip_path) as myzip:
        img_binary = myzip.read(image_name)  # 读取图片的二进制数据
    img = Image.open(BytesIO(img_binary))  # 从内存中加载图片
    return img

两种方法都能确保图片数据被完整加载到内存中,不再依赖已关闭的Zip文件对象,后续调用img.show()或np.array(img)就能正常执行。


内容的提问来源于stack exchange,提问作者Kenny Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 20:31:34