Repository navigation
Support Python 3.15 and free-threaded 3.15t #11710
Description
Python 3.15.0 is out, and conda-forge has both python-gil and python-freethreading builds. I tried running the test suite on both, as preparation for adding them to CI.
Python 3.15 (conda-forge)
- All test dependencies have 3.15 builds except pyarrow.
- The
daskmetapackage requires pyarrow, so without a lower bound the solver silently falls back to dask/distributed 2023.3.0. Usingdask-core >=2026+distributedinstead gives dask 2026.8.0, and otherwise the same versions astest-py314. - Test results: 1 failed, 22016 passed.
TestDataArray::test_to_dask_dataframeneeds pyarrow (viadask.dataframe) but is only guarded byrequires_dask.
Free-threaded Python 3.15t (PyPI wheels)
conda-forge has no free-threaded 3.15 builds of numpy, pandas, scipy etc. yet, but PyPI has cp315t wheels for numpy, pandas, scipy, pyarrow, matplotlib, cartopy, rasterio and lxml. There are no cp315t wheels for cftime, netCDF4, h5py, numcodecs, bottleneck, numexpr and numba.
With a conda python-freethreading interpreter and PyPI wheels: 150 failed, 2 errors, 14646 passed. With PYTHON_GIL=1, 148 of these still fail, so most aren't free-threading issues:
- 137: h5netcdf is installed without h5py (no
cp315twheel), sorequires_h5netcdfdoesn't skip. Environment issue. - 5:
test_ensure_warnings_not_elevated.ensure_warningsinxarray/testing/assertions.pyreassignswarnings.filters, which has no effect with context-aware warnings (sys.flags.context_aware_warnings, on by default in free-threaded builds). So the publicxr.testing.assert_*functions elevate warnings to errors there. - 3:
test_rechunk_multi_dimensional_da_cftimeis missingrequires_cftime. - 3: datatree tests assume netCDF4 is installed (
NameError: name 'nc4' is not definedin a fixture, andtest_default_write_engine).
Only 4 failures depend on the GIL: test_open_mfdataset_manyfiles[scipy-20-*-*-5] (file_cache_maxsize=5, parallel dask reads). CachingFileManager evicts and closes a scipy file opened with mmap while another thread still uses its data. The resulting RuntimeWarning leaves the LRU cache inconsistent and ends in a KeyError. These pass with PYTHON_GIL=1.
Upstream status
Python 3.15 (checked when there are builds on conda-forge and wheels on PyPI):
- numpy: 2.5.4 on conda-forge and PyPI
- numba: 0.68.0 on conda-forge and PyPI (Python 3.15 numba/numba#10581)
- dask: pure Python (on conda-forge use
dask-core; thedaskmetapackage needs pyarrow) - netCDF4:
abi3builds of 1.7.4 on conda-forge and PyPI - h5netcdf: pure Python
- bottleneck: 1.6.0 on conda-forge; PyPI wheels need a release (support merged in TST/WHL: add support for CPython 3.15 bottleneck#589, release requested in REL: new release needed bottleneck#591)
Check when: a bottleneck release after 1.6.0 shipscp315wheels on PyPI. - cftime: 1.6.5 on conda-forge,
abi3wheels of 1.6.6 on PyPI - numcodecs: 0.17.0 on conda-forge; no PyPI wheels: Wheels for Python 3.15 and 3.15t zarr-developers/numcodecs#874 (Start testing python 3.15 zarr-developers/numcodecs#842 was closed without merging)
Check when: a numcodecs release shipscp315wheels on PyPI (0.17.0 doesn't). - pyarrow: wheels of 26.0.0 on PyPI;
py315builds of 25.0.0 on conda-forge (Rebuild for python 3.15 conda-forge/pyarrow-feedstock#184) - h5py: 3.16.0 on conda-forge; no PyPI wheels: Python 3.15 compatible wheels (limited ABI?) h5py/h5py#2972 (closed;
abi3wheels from REL: publish trailing abi3 wheels in addition to version-specific ones h5py/h5py#2885 are not released yet)
Check when: an h5py release shipscp315orabi3wheels on PyPI (3.16.0 has neither). - numexpr: 2.14.2 on conda-forge; no PyPI wheels: Python 3.15 wheels numexpr#579
Check when: a numexpr release shipscp315wheels on PyPI (2.14.2 doesn't). - cf-units (needed by iris):
abi3builds of 3.3.1 on conda-forge and PyPI - pyyaml (needed by dask): 6.0.3 on conda-forge; no PyPI wheels: Python 3.15 support yaml/pyyaml#951
Check when: a pyyaml release shipscp315wheels on PyPI (6.0.3 doesn't).
Free-threaded Python 3.15t (checked when there are cp315t wheels on PyPI):
- conda-forge builds: the py315 migration started in Start py315 migration conda-forge/conda-forge-pinning-feedstock#8911, but the free-threading migration only covers 3.14t so far
Check when: conda-forge starts apython315tmigration and numpy/pandas/scipy havecp315tbuilds. - numpy:
cp315twheels of 2.5.4 - numba (also needed by numbagg): Free-threading use cases and test candidates numba/numba#10473 (free-threading in general); 3.15t support is announced for the next release in Python 3.15 numba/numba#10581
Check when: a numba release shipscp315twheels on PyPI (0.68.0 only hascp315). - dask: pure Python
- netCDF4:
cp315twheels of 1.7.5 (Free-threaded wheels for Python 3.15t Unidata/netcdf4-python#1509) - h5netcdf: pure Python (but needs h5py, see below)
- bottleneck: release requested in REL: new release needed bottleneck#591 (see also Py_MOD_GIL_NOT_USED declared but global state unprotected for free-threading bottleneck#532 on free-threading safety)
Check when: a bottleneck release shipscp315twheels on PyPI. - cftime (also needed by nc-time-axis and iris):
cp315twheels of 1.6.6.1 (1.6.6 release did not include free-threaded wheels Unidata/cftime#421, WHL: include all default build targets (including free-threaded ones) Unidata/cftime#424) - numcodecs (also needed by zarr): Wheels for Python 3.15 and 3.15t zarr-developers/numcodecs#874 (see also ENH: Free-Threading (No-GIL) Support for Python 3.13+ zarr-developers/numcodecs#749 for free-threading in general; 3.14t support in Add free-threaded CPython (3.14t) support zarr-developers/numcodecs#858)
Check when: a numcodecs release shipscp315twheels on PyPI (0.17.0 doesn't). - pyarrow:
cp315twheels of 26.0.0 - h5py: Support for free-threading CPython h5py/h5py#2475 (free-threading support;
abi3twheels planned, see Python 3.15 compatible wheels (limited ABI?) h5py/h5py#2972)
Check when: an h5py release shipscp315torabi3twheels on PyPI. - numexpr: Python 3.15 wheels numexpr#579 (2.14.2 already has
cp314twheels, so the next release will likely includecp315t)
Check when: a numexpr release shipscp315twheels on PyPI. - cf-units (needed by iris): no issue yet; 3.3.1 only has
abi3wheels
Check when: a cf-units release shipscp315torabi3twheels on PyPI. - pyyaml (needed by dask): Python 3.15 support yaml/pyyaml#951 (6.0.3 already has
cp314twheels; see also Free-threaded support blockers yaml/pyyaml#870 for free-threading in general)
Check when: a pyyaml release shipscp315twheels on PyPI.
Other test dependencies without 3.15t wheels on PyPI (checked 2026-10-13): psutil and tornado (distributed), google-crc32c (zarr) and lz4 (dask extras). psutil, tornado and lz4 build from source on 3.15t; google-crc32c builds but falls back to a pure Python implementation with a RuntimeWarning on import. cf-units doesn't build without udunits2, so iris has to be left out of the 3.15t env.
Proposal for CI
- Add
test-py315alongside the 3.14 envs, and only replace 3.14 once pyarrow has 3.15 builds on conda-forge. Until then, move pyarrow from theaccelfeature into its own feature and usedask-corein the 3.15 env. - Add
test-py315t(ubuntu only) with a condapython-freethreadinginterpreter and PyPI wheels, without h5netcdf until h5py hascp315twheels. - Fix the test guards and
ensure_warningsabove, and look into the file manager race.
[This is Claude Code on behalf of Michael Niklas]
Activity
welcome commentedon Oct 12, 2026
Thanks for opening your first issue here at xarray! Be sure to follow the issue template!
If you have an idea for a solution, we would really welcome a Pull Request with proposed changes.
See the Contributing Guide for more.
It may take us a while to respond here, but we really value your contribution. Contributors like you help make xarray better.
Thank you!
headtr1ck commentedon Oct 12, 2026
I would propose to do it in two batches
headtr1ck commentedon Oct 14, 2026
Seems like the main stopper right now is actually pyyaml, haha.
keewis commentedon Oct 24, 2026
see #11801. Most of this is done, except I used the default
pythonwhich is probablypython-freethreading.headtr1ck commentedon Oct 24, 2026
Is the pyyaml issue now resolved? I had the issue that without it dask resolved to an incredible old version. I'm on mobile only so I cannot check right now.
keewis commentedon Oct 24, 2026
it is using
dask=2026.8.0, so I would assume that's fine? There are nopyyamlpackages for python 3.15 yet, but the feedstock has a "rebuild for py3.15" PR.pyyamlhas anoarch: pythonversion, though, so I assume that is what is being used (which is probably slower than the compiled version).