Introduction to Xarray Backends#
In this lesson, we will learn about and how to use xarray’s backends
Learning Goals
Learn about xarray’s internal and external backends
Learn how xarray selects backend engines
Learn how to specify backend engines
What are Xarray Backends#
Xarray supports direct serialization and IO to several file formats, through the use of internal and external backends. Xarray’s internal backends cover many common data formats such as “netCDF4”, “h5netcdf”, and “zarr”. These backends provide a set of instructions that tells xarray how read data and store it into a Dataset, DataTree or DataTree model and are stored in the underlying “backend”.
Xarray also supports external backends such as “rioxarray” and “cfgrib” and even creating your own backend.
Reading a dataset with the netCDF4 engine#
We can read in a dataset by selecting the “netcdf4” engine
import xarray as xr
xr.tutorial.open_dataset("air_temperature", engine="netcdf4")
<xarray.Dataset> Size: 31MB
Dimensions: (time: 2920, lat: 25, lon: 53)
Coordinates:
* time (time) datetime64[ns] 23kB 2013-01-01 ... 2014-12-31T18:00:00
* lat (lat) float32 100B 75.0 72.5 70.0 67.5 65.0 ... 22.5 20.0 17.5 15.0
* lon (lon) float32 212B 200.0 202.5 205.0 207.5 ... 325.0 327.5 330.0
Data variables:
air (time, lat, lon) float64 31MB ...
Attributes:
Conventions: COARDS
title: 4x daily NMC reanalysis (1948)
description: Data is from NMC initialized reanalysis\n(4x/day). These a...
platform: Model
references: http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...Internal Backend Selection#
When opening a file or URL without explicitly specifying the engine parameter,
xarray automatically selects an appropriate backend based on the file path or URL.
The backends are tried in order: netcdf4 → h5netcdf → scipy → pydap → zarr.
Check for available backends#
We can get a list of our available engines with list_engines
import xarray as xr
xr.backends.list_engines()
{'netcdf4': <NetCDF4BackendEntrypoint>
Open netCDF (.nc, .nc4 and .cdf) and most HDF5 files using netCDF4 in Xarray
Learn more at https://docs.xarray.dev/en/stable/generated/xarray.backends.NetCDF4BackendEntrypoint.html,
'h5netcdf': <H5netcdfBackendEntrypoint>
Open netCDF (.nc, .nc4 and .cdf) and most HDF5 files using h5netcdf in Xarray
Learn more at https://docs.xarray.dev/en/stable/generated/xarray.backends.H5netcdfBackendEntrypoint.html,
'scipy': <ScipyBackendEntrypoint>
Open netCDF files (.nc, .cdf and .nc.gz) using scipy in Xarray
Learn more at https://docs.xarray.dev/en/stable/generated/xarray.backends.ScipyBackendEntrypoint.html,
'pydap': <PydapBackendEntrypoint>
Open remote datasets via OPeNDAP using pydap in Xarray
Learn more at https://docs.xarray.dev/en/stable/generated/xarray.backends.PydapBackendEntrypoint.html,
'rasterio': <RasterioBackend>,
'store': <StoreBackendEntrypoint>
Open AbstractDataStore instances in Xarray
Learn more at https://docs.xarray.dev/en/stable/generated/xarray.backends.StoreBackendEntrypoint.html,
'zarr': <ZarrBackendEntrypoint>
Open zarr files (.zarr) using zarr in Xarray
Learn more at https://docs.xarray.dev/en/stable/generated/xarray.backends.ZarrBackendEntrypoint.html}
Reading without specifying engine#
When opening a file or URL without explicitly specifying the engine parameter,
xarray automatically selects an appropriate backend based on the file path or URL.
The backends are tried in order: netcdf4 → h5netcdf → scipy → pydap → zarr.
In the following example this dataset is read with the “netcdf4” engine without explicitly setting the "engine=netcdf4"
xr.tutorial.open_dataset("air_temperature")
<xarray.Dataset> Size: 31MB
Dimensions: (time: 2920, lat: 25, lon: 53)
Coordinates:
* time (time) datetime64[ns] 23kB 2013-01-01 ... 2014-12-31T18:00:00
* lat (lat) float32 100B 75.0 72.5 70.0 67.5 65.0 ... 22.5 20.0 17.5 15.0
* lon (lon) float32 212B 200.0 202.5 205.0 207.5 ... 325.0 327.5 330.0
Data variables:
air (time, lat, lon) float64 31MB ...
Attributes:
Conventions: COARDS
title: 4x daily NMC reanalysis (1948)
description: Data is from NMC initialized reanalysis\n(4x/day). These a...
platform: Model
references: http://www.esrl.noaa.gov/psd/data/gridded/data.ncep.reanaly...Setting engine order#
You can customize the order in which netcdf4 backends are resolved using xr.set_options(netcdf_engine_order=)
Let’s update our engine order to have “h5netcdf” and the “netCDF4” and reopening the dataset
xr.set_options(netcdf_engine_order=["h5netcdf", "netcdf4", "scipy"])
<xarray.core.options.set_options at 0x7f515c0c86e0>
Specifying the wrong backend#
Lets trying specifying a bad engine for opening our dataset
Warning
This will fail because we cannot use the “pydap” engine to read this dataset
xr.tutorial.open_dataset("air_temperature", engine="pydap")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[5], line 1
----> 1 xr.tutorial.open_dataset("air_temperature", engine="pydap")
File ~/work/xarray-tutorial/xarray-tutorial/.pixi/envs/default/lib/python3.14/site-packages/xarray/tutorial.py:170, in open_dataset(name, cache, cache_dir, engine, **kws)
166 # retrieve the file
167 filepath = pooch.retrieve(
168 url=url, known_hash=None, path=cache_dir, downloader=downloader
169 )
--> 170 ds = _open_dataset(filepath, engine=engine, **kws)
171 if not cache:
172 ds = ds.load()
File ~/work/xarray-tutorial/xarray-tutorial/.pixi/envs/default/lib/python3.14/site-packages/xarray/backends/api.py:613, in open_dataset(filename_or_obj, engine, chunks, cache, decode_cf, mask_and_scale, decode_times, decode_timedelta, use_cftime, concat_characters, decode_coords, drop_variables, create_default_indexes, inline_array, chunked_array_type, from_array_kwargs, backend_kwargs, **kwargs)
601 decoders = _resolve_decoders_kwargs(
602 decode_cf,
603 open_backend_dataset_parameters=backend.open_dataset_parameters,
(...) 609 decode_coords=decode_coords,
610 )
612 overwrite_encoded_chunks = kwargs.pop("overwrite_encoded_chunks", None)
--> 613 backend_ds = backend.open_dataset(
614 filename_or_obj,
615 drop_variables=drop_variables,
616 **decoders,
617 **kwargs,
618 )
619 ds = _dataset_from_backend_dataset(
620 backend_ds,
621 filename_or_obj,
(...) 632 **kwargs,
633 )
634 return ds
File ~/work/xarray-tutorial/xarray-tutorial/.pixi/envs/default/lib/python3.14/site-packages/xarray/backends/pydap_.py:279, in PydapBackendEntrypoint.open_dataset(self, filename_or_obj, mask_and_scale, decode_times, concat_characters, decode_coords, drop_variables, use_cftime, decode_timedelta, group, application, session, output_grid, timeout, verify, user_charset, checksums)
257 def open_dataset(
258 self,
259 filename_or_obj: (
(...) 277 checksums=True,
278 ) -> Dataset:
--> 279 store = PydapDataStore.open(
280 url=filename_or_obj,
281 group=group,
282 application=application,
283 session=session,
284 output_grid=output_grid,
285 timeout=timeout,
286 verify=verify,
287 user_charset=user_charset,
288 checksums=checksums,
289 )
290 store_entrypoint = StoreBackendEntrypoint()
291 with close_on_error(store):
File ~/work/xarray-tutorial/xarray-tutorial/.pixi/envs/default/lib/python3.14/site-packages/xarray/backends/pydap_.py:141, in PydapDataStore.open(cls, url, group, application, session, output_grid, timeout, verify, user_charset, checksums)
130 kwargs = {
131 "url": url,
132 "application": application,
(...) 137 "user_charset": user_charset,
138 }
139 if isinstance(url, str):
140 # check uit begins with an acceptable scheme
--> 141 dataset = open_url(**kwargs)
142 elif hasattr(url, "ds"):
143 # pydap dataset
144 dataset = url.ds
File ~/work/xarray-tutorial/xarray-tutorial/.pixi/envs/default/lib/python3.14/site-packages/pydap/client.py:179, in open_url(url, application, session, output_grid, flat, timeout, verify, checksums, user_charset, protocol, batch, use_cache, session_kwargs, cache_kwargs, get_kwargs)
172 if not session:
173 session = create_session(
174 use_cache=use_cache,
175 session_kwargs=session_kwargs,
176 cache_kwargs=cache_kwargs,
177 )
--> 179 handler = DAPHandler(
180 url,
181 application,
182 session,
183 output_grid=output_grid,
184 flat=flat,
185 timeout=timeout,
186 verify=verify,
187 checksums=checksums,
188 user_charset=user_charset,
189 protocol=protocol,
190 get_kwargs=get_kwargs,
191 )
192 dataset = handler.dataset
193 dataset._session = session
File ~/work/xarray-tutorial/xarray-tutorial/.pixi/envs/default/lib/python3.14/site-packages/pydap/handlers/dap.py:131, in DAPHandler.__init__(self, url, application, session, output_grid, flat, timeout, verify, checksums, user_charset, protocol, get_kwargs)
129 self.scheme = "https"
130 else:
--> 131 self.protocol = self.determine_protocol()
133 self.projection, self.selection = parse_ce(self.query, self.protocol)
134 arg = (
135 self.scheme,
136 self.netloc,
(...) 140 self.fragment,
141 )
File ~/work/xarray-tutorial/xarray-tutorial/.pixi/envs/default/lib/python3.14/site-packages/pydap/handlers/dap.py:157, in DAPHandler.determine_protocol(self)
155 return protocol
156 else:
--> 157 raise TypeError(
158 "Invalid URL scheme - acceptable options are"
159 "`dap2`, `dap4`. `https` and `http`",
160 )
161 if self.query[:4] == "dap4":
162 return "dap4"
TypeError: Invalid URL scheme - acceptable options are`dap2`, `dap4`. `https` and `http`