|
35 | 35 | )
|
36 | 36 | from xarray.core.variable import Variable
|
37 | 37 |
|
| 38 | +try: |
| 39 | + from scipy.io import netcdf_file as netcdf_file_base |
| 40 | +except ImportError: |
| 41 | + netcdf_file_base = object |
| 42 | + |
| 43 | + |
38 | 44 | if TYPE_CHECKING:
|
39 | 45 | import scipy.io
|
40 | 46 |
|
@@ -104,31 +110,32 @@ def __setitem__(self, key, value):
|
104 | 110 | raise
|
105 | 111 |
|
106 | 112 |
|
| 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 | + |
107 | 136 | def _open_scipy_netcdf(filename, mode, mmap, version, flush_only=False):
|
108 | 137 | import scipy.io
|
109 | 138 |
|
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 |
| - |
132 | 139 | netcdf_file = flush_only_netcdf_file if flush_only else scipy.io.netcdf_file
|
133 | 140 |
|
134 | 141 | # if the string ends with .gz, then gunzip and open as netcdf file
|
|
0 commit comments