diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py index e635e97d04..19fcf7a1f8 100644 --- a/lib/iris/fileformats/cf.py +++ b/lib/iris/fileformats/cf.py @@ -70,6 +70,12 @@ ocean_s_coordinate_g2=['eta', 'depth']) +# NetCDF returns a different type for strings depending on Python version. +def _is_str_dtype(var): + return ((six.PY2 and np.issubdtype(var.dtype, np.str)) or + (six.PY3 and np.issubdtype(var.dtype, np.bytes_))) + + ################################################################################ class CFVariable(six.with_metaclass(ABCMeta, object)): """Abstract base class wrapper for a CF-netCDF variable.""" @@ -313,7 +319,7 @@ def identify(cls, variables, ignore=None, target=None, warn=True): warnings.warn(message % (name, nc_var_name)) else: # Restrict to non-string type i.e. not a CFLabelVariable. - if not np.issubdtype(variables[name].dtype, np.str): + if not _is_str_dtype(variables[name]): result[name] = CFAuxiliaryCoordinateVariable(name, variables[name]) return result @@ -478,7 +484,7 @@ def identify(cls, variables, ignore=None, target=None, warn=True, monotonic=Fals if nc_var_name in ignore: continue # String variables can't be coordinates - if np.issubdtype(nc_var.dtype, np.str): + if _is_str_dtype(nc_var): continue # Restrict to one-dimensional with name as dimension OR zero-dimensional scalar if not ((nc_var.ndim == 1 and nc_var_name in nc_var.dimensions) or (nc_var.ndim == 0)): @@ -638,8 +644,9 @@ def identify(cls, variables, ignore=None, target=None, warn=True): warnings.warn(message % (name, nc_var_name)) else: # Restrict to only string type. - if np.issubdtype(variables[name].dtype, np.str): - result[name] = CFLabelVariable(name, variables[name]) + if _is_str_dtype(variables[name]): + var = variables[name] + result[name] = CFLabelVariable(name, var) return result @@ -683,7 +690,7 @@ def cf_label_data(self, cf_data_var): # Calculate new label data shape (without string dimension) and create payload array. new_shape = tuple(dim_len for i, dim_len in enumerate(self.shape) if i != str_dim) - data = np.empty(new_shape, dtype='|S%d' % self.shape[str_dim]) + data = np.empty(new_shape, dtype='|U%d' % self.shape[str_dim]) for index in np.ndindex(new_shape): # Create the slice for the label data. @@ -692,7 +699,8 @@ def cf_label_data(self, cf_data_var): else: label_index = index + (slice(None, None),) - data[index] = ''.join(label_data[label_index]).strip() + data[index] = b''.join(label_data[label_index]).strip().decode( + 'utf8') return data