Skip to content

Commit 349e7db

Browse files
committed
Fixes too many files open error: h5netcdf backend
1 parent 6d313e4 commit 349e7db

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

xarray/backends/h5netcdf_.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from __future__ import division
33
from __future__ import print_function
44
import functools
5+
import contextlib
56

67
from .. import Variable
78
from ..core import indexing
@@ -36,6 +37,11 @@ def _read_attributes(h5netcdf_var):
3637
_extract_h5nc_encoding = functools.partial(_extract_nc4_encoding,
3738
lsd_okay=False, backend='h5netcdf')
3839

40+
def _close_ds(ds):
41+
# netCDF4 only allows closing the root group
42+
while ds.parent is not None:
43+
ds = ds.parent
44+
ds.close()
3945

4046
def _open_h5netcdf_group(filename, mode, group):
4147
import h5netcdf.legacyapi
@@ -54,12 +60,20 @@ def __init__(self, filename, mode='r', format=None, group=None,
5460
opener = functools.partial(_open_h5netcdf_group, filename, mode=mode,
5561
group=group)
5662
self.ds = opener()
63+
self._isopen = True
5764
self.format = format
5865
self._opener = opener
5966
self._filename = filename
6067
self._mode = mode
6168
super(H5NetCDFStore, self).__init__(writer)
6269

70+
@contextlib.contextmanager
71+
def ensure_open(self):
72+
if not self._isopen:
73+
self.ds = self._opener()
74+
self._isopen = True
75+
yield
76+
6377
def open_store_variable(self, name, var):
6478
dimensions = var.dimensions
6579
data = indexing.LazilyIndexedArray(BaseNetCDF4Array(name, self))
@@ -77,20 +91,25 @@ def open_store_variable(self, name, var):
7791
return Variable(dimensions, data, attrs, encoding)
7892

7993
def get_variables(self):
80-
return FrozenOrderedDict((k, self.open_store_variable(k, v))
81-
for k, v in iteritems(self.ds.variables))
94+
with self.ensure_open():
95+
return FrozenOrderedDict((k, self.open_store_variable(k, v))
96+
for k, v in iteritems(self.ds.variables))
8297

8398
def get_attrs(self):
84-
return Frozen(_read_attributes(self.ds))
99+
with self.ensure_open():
100+
return Frozen(_read_attributes(self.ds))
85101

86102
def get_dimensions(self):
87-
return self.ds.dimensions
103+
with self.ensure_open():
104+
return self.ds.dimensions
88105

89106
def set_dimension(self, name, length):
90-
self.ds.createDimension(name, size=length)
107+
with self.ensure_open():
108+
self.ds.createDimension(name, size=length)
91109

92110
def set_attribute(self, key, value):
93-
self.ds.setncattr(key, value)
111+
with self.ensure_open():
112+
self.ds.setncattr(key, value)
94113

95114
def prepare_variable(self, name, variable, check_encoding=False):
96115
import h5py
@@ -123,12 +142,11 @@ def prepare_variable(self, name, variable, check_encoding=False):
123142
return nc4_var, variable.data
124143

125144
def sync(self):
126-
super(H5NetCDFStore, self).sync()
127-
self.ds.sync()
145+
with self.ensure_open():
146+
super(H5NetCDFStore, self).sync()
147+
self.ds.sync()
128148

129149
def close(self):
130-
ds = self.ds
131-
# netCDF4 only allows closing the root group
132-
while ds.parent is not None:
133-
ds = ds.parent
134-
ds.close()
150+
if self._isopen:
151+
self._isopen = False
152+
_close_ds(self.ds)

0 commit comments

Comments
 (0)