2020import re
2121import warnings
2222
23- import netCDF4
2423import numpy as np
2524import numpy .ma as ma
2625
26+ from iris .fileformats .netcdf import _thread_safe_nc
2727import iris .util
2828
2929#
@@ -1050,7 +1050,9 @@ def __init__(self, filename, warn=False, monotonic=False):
10501050 #: Collection of CF-netCDF variables associated with this netCDF file
10511051 self .cf_group = self .CFGroup ()
10521052
1053- self ._dataset = netCDF4 .Dataset (self ._filename , mode = "r" )
1053+ self ._dataset = _thread_safe_nc .DatasetWrapper (
1054+ self ._filename , mode = "r"
1055+ )
10541056
10551057 # Issue load optimisation warning.
10561058 if warn and self ._dataset .file_format in [
@@ -1068,6 +1070,19 @@ def __init__(self, filename, warn=False, monotonic=False):
10681070 self ._build_cf_groups ()
10691071 self ._reset ()
10701072
1073+ def __enter__ (self ):
1074+ # Enable use as a context manager
1075+ # N.B. this **guarantees* closure of the file, when the context is exited.
1076+ # Note: ideally, the class would not do so much work in the __init__ call, and
1077+ # would do all that here, after acquiring necessary permissions/locks.
1078+ # But for legacy reasons, we can't do that. So **effectively**, the context
1079+ # (in terms of access control) alreday started, when we created the object.
1080+ return self
1081+
1082+ def __exit__ (self , exc_type , exc_value , traceback ):
1083+ # When used as a context-manager, **always** close the file on exit.
1084+ self ._close ()
1085+
10711086 @property
10721087 def filename (self ):
10731088 """The file that the CFReader is reading."""
@@ -1294,10 +1309,15 @@ def _reset(self):
12941309 for nc_var_name in self ._dataset .variables .keys ():
12951310 self .cf_group [nc_var_name ].cf_attrs_reset ()
12961311
1297- def __del__ (self ):
1312+ def _close (self ):
12981313 # Explicitly close dataset to prevent file remaining open.
12991314 if self ._dataset is not None :
13001315 self ._dataset .close ()
1316+ self ._dataset = None
1317+
1318+ def __del__ (self ):
1319+ # Be sure to close dataset when CFReader is destroyed / garbage-collected.
1320+ self ._close ()
13011321
13021322
13031323def _getncattr (dataset , attr , default = None ):
0 commit comments