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

从Azure数据存储加载图片转Dataset时触发StreamClosed错误

问题:Azure ML Notebook中加载图片到Dataset时出现StreamClosed错误

我按照教程方法把Azure数据存储里的图片加载到Azure AI Machine Learning Studio notebook,图片能正常加载,但把包含图片的字典转成Dataset对象时,抛出StreamClosed错误。

原代码

from azureml.fsspec import AzureMachineLearningFileSystem
import datasets import Dataset
from PIL import Image

fs = AzureMachineLearningFileSystem('path_to_my_datastore')

file_list = ['file1', 'file2', 'file3']

img_lst = []

for file in file_list:
    with fs.open('data_direc/'+file+'.jpg') as f:
        img = Image.open(f)
        img_lst.append(img)

test_dict = {'image': img_lst}

Dataset.from_dict(test_dict)

报错信息

---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
Cell In[88], line 1
----> 1 Dataset.from_dict(data_dict)

File /anaconda/envs/main-env/lib/python3.11/site-packages/datasets/arrow_dataset.py:912, in Dataset.from_dict(cls, mapping, features, info, split)
    910     arrow_typed_mapping[col] = data
    911 mapping = arrow_typed_mapping
---> 912 pa_table = InMemoryTable.from_pydict(mapping=mapping)
    913 if info is None:
    914     info = DatasetInfo()

File /anaconda/envs/main-env/lib/python3.11/site-packages/datasets/table.py:758, in InMemoryTable.from_pydict(cls, *args, **kwargs)
    742 @classmethod
    743 def from_pydict(cls, *args, **kwargs):
    744     """
    745     Construct a Table from Arrow arrays or columns.
    746 
   (...)
    756         `datasets.table.Table`
    757     """
---> 758     return cls(pa.Table.from_pydict(*args, **kwargs))

File /anaconda/envs/main-env/lib/python3.11/site-packages/pyarrow/table.pxi:1813, in pyarrow.lib._Tabular.from_pydict()

File /anaconda/envs/main-env/lib/python3.11/site-packages/pyarrow/table.pxi:5347, in pyarrow.lib._from_pydict()

File /anaconda/envs/main-env/lib/python3.11/site-packages/pyarrow/array.pxi:373, in pyarrow.lib.asarray()

File /anaconda/envs/main-env/lib/python3.11/site-packages/pyarrow/array.pxi:247, in pyarrow.lib.array()

File /anaconda/envs/main-env/lib/python3.11/site-packages/pyarrow/array.pxi:112, in pyarrow.lib._handle_arrow_array_protocol()

File /anaconda/envs/main-env/lib/python3.11/site-packages/datasets/arrow_writer.py:169, in TypedSequence.__arrow_array__(***failed resolving arguments***)
    167 # automatic type inference for custom objects
    168 if self.type is None and self.try_type is None:
---> 169     data, self._inferred_type = self._infer_custom_type_and_encode(data)
    170 if self._inferred_type is None:
    171     type = self.try_type if self.trying_type else self.type

File /anaconda/envs/main-env/lib/python3.11/site-packages/datasets/arrow_writer.py:157, in TypedSequence._infer_custom_type_and_encode(data)
    155     non_null_idx, non_null_value = first_non_null_value(data)
    156     if isinstance(non_null_value, PIL.Image.Image):
---> 157         return [Image().encode_example(value) if value is not None else None for value in data], Image()
    158 return data, None

File /anaconda/envs/main-env/lib/python3.11/site-packages/datasets/arrow_writer.py:157, in <listcomp>(.0)
    155     non_null_idx, non_null_value = first_non_null_value(data)
    156     if isinstance(non_null_value, PIL.Image.Image):
---> 157         return [Image().encode_example(value) if value is not None else None for value in data], Image()
    158 return data, None

File /anaconda/envs/main-env/lib/python3.11/site-packages/datasets/features/image.py:119, in Image.encode_example(self, value)
    116     return encode_np_array(value)
    117 elif isinstance(value, PIL.Image.Image):
    118     # convert the PIL image to bytes (default format is PNG/TIFF)
---> 119     return encode_pil_image(value)
    120 elif value.get("path") is not None and os.path.isfile(value["path"]):
    121     # we set "bytes": None to not duplicate the data if they're already available locally
    122     return {"bytes": None, "path": value.get("path")}

File /anaconda/envs/main-env/lib/python3.11/site-packages/datasets/features/image.py:308, in encode_pil_image(image)
    306     return {"path": image.filename, "bytes": None}
    307 else:
---> 308     return {"path": None, "bytes": image_to_bytes(image)}

File /anaconda/envs/main-env/lib/python3.11/site-packages/datasets/features/image.py:300, in image_to_bytes(image)
    298 else:
    299     format = "PNG" if image.mode in ["1", "L", "LA", "RGB", "RGBA"] else "TIFF"
---> 300 image.save(buffer, format=format)
    301 return buffer.getvalue()

File /anaconda/envs/main-env/lib/python3.11/site-packages/PIL/Image.py:2421, in Image.save(self, fp, format, **params)
   2418     filename = os.path.realpath(os.fspath(fp.name))
   2420 # may mutate self!
---> 2421 self._ensure_mutable()
   2423 save_all = params.pop("save_all", False)
   2424 self.encoderinfo = params

File /anaconda/envs/main-env/lib/python3.11/site-packages/PIL/Image.py:595, in Image._ensure_mutable(self)
    593 def _ensure_mutable(self) -> None:
    594     if self.readonly:
---> 595         self._copy()
    596     else:
    597         self.load()

File /anaconda/envs/main-env/lib/python3.11/site-packages/PIL/Image.py:588, in Image._copy(self)
    587 def _copy(self) -> None:
---> 588     self.load()
    589     self.im = self.im.copy()
    590     self.pyaccess = None

File /anaconda/envs/main-env/lib/python3.11/site-packages/PIL/ImageFile.py:258, in ImageFile.load(self)
    251 self.tile = [
    252     list(tiles)[-1]
    253     for _, tiles in itertools.groupby(
    254         self.tile, lambda tile: (tile[0], tile[1], tile[3])
    255     )
    256 ]
    257 for decoder_name, extents, offset, args in self.tile:
---> 258     seek(offset)
    259     decoder = Image._getdecoder(
    260         self.mode, decoder_name, args, self.decoderconfig
    261     )
    262     try:

File pystreaminfo_companion.py:23, in seek(self, offset, whence)

Exception: StreamClosed
解决方案

问题根源是PIL的延迟加载机制:Image.open(f)并没有立即读取流中的所有数据,只是创建了一个指向该流的Image对象。当with fs.open(...)代码块结束时,Azure存储的文件流会被关闭。之后Dataset.from_dict尝试编码Image对象时,需要重新读取流数据,但此时流已经关闭,所以抛出StreamClosed错误。

方法1:强制加载图片到内存

在with代码块内,调用img.copy()或者img.load()把图片数据全部加载到内存,让Image对象脱离原文件流的依赖:

from azureml.fsspec import AzureMachineLearningFileSystem
from datasets import Dataset
from PIL import Image

fs = AzureMachineLearningFileSystem('path_to_my_datastore')

file_list = ['file1', 'file2', 'file3']

img_lst = []

for file in file_list:
    with fs.open('data_direc/'+file+'.jpg') as f:
        img = Image.open(f)
        # 强制加载图片数据到内存
        img = img.copy()  # 或使用 img.load()
        img_lst.append(img)

test_dict = {'image': img_lst}

Dataset.from_dict(test_dict)

方法2:读取字节数据后创建Image对象

先读取流中的所有字节数据,再用字节数据创建Image对象,完全不依赖原文件流:

from azureml.fsspec import AzureMachineLearningFileSystem
from datasets import Dataset
from PIL import Image
import io

fs = AzureMachineLearningFileSystem('path_to_my_datastore')

file_list = ['file1', 'file2', 'file3']

img_lst = []

for file in file_list:
    with fs.open('data_direc/'+file+'.jpg') as f:
        # 读取全部字节数据
        img_bytes = f.read()
        # 用字节数据创建Image对象
        img = Image.open(io.BytesIO(img_bytes))
        img_lst.append(img)

test_dict = {'image': img_lst}

Dataset.from_dict(test_dict)

额外修正

原代码存在import语法错误:import datasets import Dataset应改为from datasets import Dataset,上述修复代码已修正该问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 06:25:53