Проблема
Не уверен насчет остальной части вашего кода, но вы не можете использовать шаблон диспетчера контекста (например, with h5py.File(foo) as bar:
) в функции, которая возвращает набор данных.Как вы указали в комментарии под своим вопросом, это означает, что к тому времени, когда вы попытаетесь получить доступ к набору данных, фактический файл HDF5 уже будет закрыт.Объекты набора данных в h5py
подобны интерактивным представлениям в файле, поэтому для их использования требуется, чтобы файл оставался открытым.Таким образом, вы получаете ошибки.
Решение
Хорошая идея - всегда взаимодействовать с файлами в управляемом контексте (то есть в предложении with
).Если ваш код выдает ошибку, менеджер контекста (почти всегда) гарантирует, что файл закрыт.Это помогает избежать любых потенциальных потерь данных в результате сбоя.
В вашем случае вы можете иметь свой торт (инкапсулировать подпрограммы создания набора данных в отдельной функции) и съесть его тоже (взаимодействовать с файлом HDF5 внутриуправляемый контекст), написав свой собственный менеджер контекста, который позаботится о вас.
На самом деле это довольно просто кодировать.Любой объект Python, который реализует методы __enter__
и __exit__
, является допустимым диспетчером контекста.Вот полная рабочая версия:
import os
import h5py
import numpy as np
path = './out.h5'
try:
os.remove(path)
except OSError:
pass
class H5PYManager:
def __init__(self, path, method='a'):
self.hf = h5py.File(path, method)
def __enter__(self):
# when you call `with H5PYManager(foo) as bar`, the return of this method will be assigned to `bar`
return self.create_datasets()
def __exit__(self, type, value, traceback):
# this method gets called when you exit the `with` clause, including when an error is raised
self.hf.close()
def create_datasets(self):
grp = self.hf.create_group('left')
return [grp.create_dataset('voltage', (10**4,3), maxshape=(None,3), dtype='f', chunks=(10**4,3)),
grp.create_dataset('current', (10**4,3), maxshape=(None,3), dtype='f', chunks=(10**4,3))]
if __name__ == '__main__':
with H5PYManager(path) as dset:
for i in range(3):
if i == 0:
dset[0][:] = np.random.random(dset[0].shape)
dset[1][:] = np.random.random(dset[1].shape)
else:
dset[0].resize(dset[0].shape[0]+10**4, axis=0)
dset[0][-10**4:] = np.random.random((10**4,3))
dset[1].resize(dset[1].shape[0]+10**4, axis=0)
dset[1][-10**4:] = np.random.random((10**4,3))