Skip to content

Commit 5a2dc42

Browse files
committed
Make scipy import no longer lazy
1 parent 2100673 commit 5a2dc42

File tree

2 files changed

+30
-23
lines changed

2 files changed

+30
-23
lines changed

xarray/backends/scipy_.py

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@
3535
)
3636
from xarray.core.variable import Variable
3737

38+
try:
39+
from scipy.io import netcdf_file as netcdf_file_base
40+
except ImportError:
41+
netcdf_file_base = object
42+
43+
3844
if TYPE_CHECKING:
3945
import scipy.io
4046

@@ -104,31 +110,32 @@ def __setitem__(self, key, value):
104110
raise
105111

106112

113+
# TODO: Make the scipy import lazy again after upstreaming these fixes.
114+
class flush_only_netcdf_file(netcdf_file_base):
115+
# scipy.io.netcdf_file.close() incorrectly closes file objects that
116+
# were passed in as constructor arguments:
117+
# https://github.com/scipy/scipy/issues/13905
118+
119+
# Instead of closing such files, only call flush(), which is
120+
# equivalent as long as the netcdf_file object is not mmapped.
121+
# This suffices to keep BytesIO objects open long enough to read
122+
# their contents from to_netcdf(), but underlying files still get
123+
# closed when the netcdf_file is garbage collected (via __del__),
124+
# and will need to be fixed upstream in scipy.
125+
def close(self):
126+
if hasattr(self, "fp") and not self.fp.closed:
127+
self.flush()
128+
self.fp.seek(0) # allow file to be read again
129+
130+
def __del__(self):
131+
# Remove the __del__ method, which in scipy is aliased to close().
132+
# These files need to be closed explicitly by xarray.
133+
pass
134+
135+
107136
def _open_scipy_netcdf(filename, mode, mmap, version, flush_only=False):
108137
import scipy.io
109138

110-
# define inside a helper function to ensure the scipy import is lazy
111-
class flush_only_netcdf_file(scipy.io.netcdf_file):
112-
# scipy.io.netcdf_file.close() incorrectly closes file objects that
113-
# were passed in as constructor arguments:
114-
# https://github.com/scipy/scipy/issues/13905
115-
116-
# Instead of closing such files, only call flush(), which is
117-
# equivalent as long as the netcdf_file object is not mmapped.
118-
# This suffices to keep BytesIO objects open long enough to read
119-
# their contents from to_netcdf(), but underlying files still get
120-
# closed when the netcdf_file is garbage collected (via __del__),
121-
# and will need to be fixed upstream in scipy.
122-
def close(self):
123-
if hasattr(self, "fp") and not self.fp.closed:
124-
self.flush()
125-
self.fp.seek(0) # allow file to be read again
126-
127-
def __del__(self):
128-
# Remove the __del__ method, which in scipy is aliased to close().
129-
# These files need to be closed explicitly by xarray.
130-
pass
131-
132139
netcdf_file = flush_only_netcdf_file if flush_only else scipy.io.netcdf_file
133140

134141
# if the string ends with .gz, then gunzip and open as netcdf file

xarray/tests/test_plugins.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def test_lazy_import() -> None:
227227
"numbagg",
228228
"pint",
229229
"pydap",
230-
"scipy",
230+
# "scipy", # TODO: xarray.backends.scipy_ is currently not lazy
231231
"sparse",
232232
"zarr",
233233
]

0 commit comments

Comments
 (0)