# iris: format-agnostic Earth science analysis for Python teams

> SciTools/iris is a BSD-3-Clause Python package for analysing and visualising Earth science data, published on PyPI as scitools-iris and on conda-forge as iris, and it requires Python 3.12 or newer. Its distinctive machinery is a build step that compiles the CF standard name table into a Python module before the package is built.

**SciTools/iris** — A powerful, format-agnostic, and community-driven Python package for analysing and visualising Earth science data

- Repository: https://github.com/SciTools/iris
- Website: https://scitools-iris.readthedocs.io/en/stable/
- Stars: 729 · Forks: 320
- Language: Python
- License: BSD-3-Clause
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/scitools-iris

## One package for Earth science data across formats

SciTools/iris is described as a format-agnostic, community-driven Python package for analysing and visualising Earth science data. The topic tags on the repository give a clear picture of the domain: data-analysis, earth-science, grib, netcdf, meteorology, oceanography, space-weather and visualisation.

So the audience is climate, ocean and atmospheric science teams, plus the software engineers who support them. The problem it addresses is that this kind of data arrives in incompatible shapes, and every format has its own reader, its own conventions and its own idea of what a dimension means. A package that hides that behind one Python interface saves the group from maintaining a pile of format-specific loading code.

The metadata keywords carry the other half of the story: cf-metadata and ugrid alongside the format names. Iris is built around the CF conventions rather than around any single file format, which is what makes the format-agnostic claim plausible rather than a slogan. The documentation site, hosted on Read the Docs, has a latest developer version and a most recent released stable version, and the project also publishes a Zenodo DOI, which is the sort of detail that matters when a dataset or analysis has to be cited.

The project describes itself as community-driven, and the repository is built by a named set of contributors rather than a single vendor, with GitHub Discussions and a Bluesky account listed as community channels.

## PyPI, conda-forge and a Python 3.12 floor

Two distribution channels are advertised in the package metadata. The PyPI project is named scitools-iris, and the conda-forge package is named iris. The name difference is the first thing that trips people up, so it is worth being explicit: the import name, the PyPI distribution name and the conda package name are not the same string.

The interpreter requirement is the harder boundary. The pyproject file sets requires-python to >=3.12, and the classifiers list Python 3.12, 3.13 and 3.14 only, with the CPython implementation specified and the 3 only marker present. Any analysis environment still on 3.11 or older is excluded outright.

Platform coverage is declared for MacOS, POSIX, POSIX Linux and Unix. No Windows classifier appears, which tells you something about where the project tests and supports its installs, and it is a fair question to raise with the maintainers if your team is on Windows.

The licence is BSD-3-Clause, with the licence file listed in the packaging metadata, and the classifiers call the project Development Status 5 - Production/Stable with an Intended Audience of Science and Research. For a research tool, that audience marker is a signal about who the maintainers optimise for, and it aligns with the project's reliance on scientific Python packaging practice.

A useful extra piece of release hygiene is present too: a CITATION.cff file at the repository root, which is how the project makes itself citable in a way that survives a repository rename or a moving maintainer.

## A build step compiles the CF standard name table

The most distinctive thing in the repository is a custom setuptools command. The setup.py file defines a helper that wraps a build_py command and adds behaviour to build the CF standard names module.

```python
def custom_command(cmd, help=""):
    """Create custom command with factory function.

    Custom command will add additional behaviour to build the CF
    standard names module.

    """
```

The command calls out to a script in the tools directory to build the module.

```python
        def _build_std_names(self, directory):
            # Call out to tools/generate_std_names.py to build std_names module.

            script_path = os.path.join("tools", "generate_std_names.py")
            xml_path = os.path.join("etc", "cf-standard-name-table.xml")
            module_path = os.path.join(directory, "iris", "std_names.py")
            args = [sys.executable, script_path, xml_path, module_path]
            self.spawn(args)
```

In other words, the XML standard name table that ships in the etc directory is turned into a Python module named std_names.py as part of the build, and the command forces editable mode on by default so that the generated module is present in a development checkout as well as in a wheel.

Two consequences follow for anyone building or packaging this project. The generated files are excluded from the manifest check, because lib/iris/std_names.py and lib/iris/_version.py are produced rather than authored, and the project does not keep them in the tree as source. And a downstream user does not parse the CF table at runtime; they get a Python module compiled from the table that shipped with the version they installed, which means the standards content is tied to the release rather than to whatever the table says today.

## The repository carries its own test, lint and environment machinery

This is a project that invests in its development environment, and the file list shows it. There is a noxfile.py for driving test sessions, an environment.yml for a conda environment, a requirements directory with lock files, a Makefile, a pre-commit configuration, a Ruff badge, a codecov configuration and a benchmarks directory.

The lock files are refreshed with a dedicated script, and the Makefile exposes that as a single target.

```bash
lockfiles:
	python tools/update_lockfiles.py -o requirements/locks requirements/py*.yml
```

The target takes every environment file matching requirements/py*.yml and writes updated locks into requirements/locks, which is how a project supporting several Python versions keeps a pinned dependency set per version.

Continuous integration is split into separate workflows visible in the README badges: ci-tests, ci-wheels, ci-manifest and ci-linkchecks, with pre-commit also running as a hosted check. Splitting wheels from tests means the packaging matrix is verified separately from the test matrix, and the link check workflow guards the documentation, which matters in a project where the docs carry most of the usage information.

The code lives under lib/ in a src-style layout, the package is built with setuptools and setuptools_scm, and the version is dynamic rather than written by hand, which is why the generated lib/iris/_version.py is ignored by the manifest check alongside the standard names module.

## Three releases in ten weeks and a stated deprecation policy

Iris ships on a visible cadence. v3.16.0 was released on 2026-08-13, v3.16.1 on 2026-09-24 and v3.16.2 on 2026-10-06, and the last push to the repository was on 2026-10-17. The repository is not archived, and the project does not claim a fixed release schedule but the tags show a steady run of patch and minor releases.

The version numbers carry meaning for anyone planning an upgrade. A 3.16.2 to 3.17 step is the ordinary case, but a move across minor versions is where deprecations bite, and the project states that it follows NEP29, the NumPy deprecation policy, which is the convention of announcing a removal with a transition period rather than deleting an API silently. That is a commitment you can plan around, and it also means the changelog is the place to read before any dependency bump.

The upgrade cost has two layers. The dependency layer is handled by the lock files, which give you a known-good set per Python version to start from. The API layer is where the work sits, and it is driven by the CF standards content the package compiles in, so a release can change what names are available in std_names without the shape of your code changing.

The licence position is simple and stable: BSD-3-Clause with the licence file at the repository root, which permits reuse in commercial and closed work provided the notice is kept, and the project also states that it follows the Contributor Covenant 2.1 as its code of conduct.

## The README is a badge wall, and the real documentation is elsewhere

It is worth being direct about what a new user finds. The README is mostly a table of status badges, a link to the documentation, and a reproduction of the ShowYourStripes warming stripes graphic with graphics and lead scientist credited to Ed Hawkins. There is no installation snippet, no example script and no quickstart in it. Nothing in the repository file list fills that gap either, since there is no examples directory.

So the documentation site carries the load, and the README points to a latest developer version alongside a stable one. The distinction matters for users: the stable documentation matches the released package, while the latest documentation matches the main branch, which after a push on 2026-10-17 is ahead of v3.16.2.

That is the main practical limitation for anyone evaluating iris from the repository alone. You cannot judge the API surface, the data model or the plotting behaviour from what is in the repository, so an evaluation means reading the hosted docs and the changelog rather than skimming a readme.

The second limitation is the Python floor. Requiring 3.12 or newer excludes a large part of the installed scientific Python estate, and because the project also publishes pinned lock files per Python version, you are expected to work inside the supported matrix rather than an arbitrary environment.

## Building your own CF name table versus depending on iris to compile it

The genuine alternative to adopting iris is to work with the CF standard name table directly and treat the format-specific parts of your pipeline as your own code. The repository makes that comparison concrete, because etc/cf-standard-name-table.xml is right there in the tree, and the package's own approach is to compile that XML into a Python module at build time with tools/generate_std_names.py.

The difference in approach is where the work sits. Writing your own reader means you own the parsing, the mapping of names to your own structures, and the updates as the table changes, and you own the format-specific loading code for each file type you meet. Taking iris means the compilation step, the packaging of the result and the format handling arrive with the package, and your code depends on a released artefact whose contents are pinned to a version, with a DOI to cite when you publish results.

A middle path exists, and it is worth naming: use the same standards table as your source of truth without adopting the package, for instance if your workflow only needs a name lookup and not the analysis and visualisation layer. The cost of that choice is that you reimplement the build-time generation yourself, which is precisely the work the setup.py custom command performs for iris users.

Whichever route you take, the table itself is the shared contract, and checking it against the standards your own data files use is the step that prevents silent mismatches later.

## Conclusion

iris fits research and engineering groups working with CF-style Earth science data across formats such as netCDF and GRIB who want one Python package for analysis and visualisation with a published DOI for citation. It does not fit environments stuck on Python 3.11 or older, since the package requires 3.12, and the classifiers list only MacOS, POSIX, Unix and Linux, so Windows support is not claimed. Before adopting it, check the Python version and platform classifiers in pyproject.toml, read the lock files under requirements/locks to see the pinned dependency set, and confirm that the CF standard name table in etc/cf-standard-name-table.xml matches the standards your own data uses.

## FAQ

### Which Python versions does iris support and where is it installed from?

The pyproject metadata sets requires-python to >=3.12 and classifies Python 3.12, 3.13 and 3.14. The package is published on PyPI as scitools-iris and on conda-forge as iris.

### What licence is the SciTools iris package released under?

The package is BSD-3-Clause, with the licence file listed in the packaging metadata and a LICENSE file at the repository root. The project also publishes a Zenodo DOI and a CITATION.cff file for citation.

### How does iris generate its CF standard names module?

A custom setuptools command in setup.py calls tools/generate_std_names.py with etc/cf-standard-name-table.xml to build lib/iris/std_names.py during the build, and it enables editable mode by default. The generated files are excluded from the manifest check.

### Where can I find the iris documentation and how do releases work?

Documentation is hosted on Read the Docs with a latest developer version and a stable version matching the most recent release. Recent tags include v3.16.0 on 2026-08-13, v3.16.1 on 2026-09-24 and v3.16.2 on 2026-10-06.

### How do the iris dependency lock files get refreshed?

The Makefile has a lockfiles target that runs `python tools/update_lockfiles.py -o requirements/locks requirements/py*.yml`, writing updated locks from the environment files under requirements into requirements/locks.

## Sources

- [License: BSD-3-Clause](https://github.com/SciTools/iris/blob/main/LICENSE)
- [Project website](https://scitools-iris.readthedocs.io/en/stable/)
- [README](https://github.com/SciTools/iris/blob/main/README.md)
- [Releases](https://github.com/SciTools/iris/releases)
- [SciTools/iris on GitHub](https://github.com/SciTools/iris)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/scitools-iris
