pint-cf
This package extends Pint with a CF-compliant unit registry and formatter.
Features
- A CF-compliant Pint
UnitRegistry, understanding UDUNITS-2 unit strings. - A
cfformat forUnit/Quantity, to write results back out as CF strings. CFContext, to correctly read CF'sunits_metadatatemperature attribute.- CF units that UDUNITS-2 itself doesn't define (
level,psu,decibel,sverdrup'sSvsymbol, ...), included by default.
Known limitations:
- No support for time coordinates (e.g.
days since 2001-01-01) or climate calendars (e.g.360_day). Use cftime for those instead. decibel/belare treated as plain dimensionless ratio units, matchingcfunits/cf-units- CF's own reference level for adBvalue depends on the variable'sstandard_name, but neither of those reference packages resolves it either, so pint-cf follows the same convention rather than the letter of the spec.
Installation
Install via pip:
pip install pint-cf
Usage
Create a CF-ready unit registry with cf_unitregistry(). This also
registers the cf format.
from pint_cf import cf_unitregistry
ureg = cf_unitregistry()
q = ureg('10 meters per second^2').to('km s-2')
print(f"{q:cf}") # 0.01 kilometer-second^-2
print(f"{q:~cf}") # 0.01 km/s2
Temperature units_metadata
CF distinguishes an on-scale temperature (e.g. today's temperature) from a
temperature difference (e.g. an anomaly) with a units_metadata
attribute - the plain units string alone can't tell them apart.
When reading a variable that has this attribute, wrap the value in
CFContext:
from pint_cf import cf_unitregistry, CFContext
ureg = cf_unitregistry()
with CFContext(units_metadata="temperature: difference"):
q = ureg.Quantity(1, "degree_C")
print(q.units) # delta_degree_Celsius
Without CFContext (or with units_metadata absent), nothing changes - an
on-scale temperature is read as usual.
When writing a result back out, cf_attributes_for does the reverse: it
derives the units_metadata attribute from an already-computed Unit or
Quantity, ready to merge into a NetCDF variable's attributes:
from pint_cf import cf_attributes_for
print(cf_attributes_for(q)) # {"units_metadata": "temperature: difference"}
print(cf_attributes_for(ureg.Unit("meter"))) # {} - not a temperature unit
ds[name].attrs.update(cf_attributes_for(q.units))
This round-trips exactly for Celsius and Fahrenheit. Kelvin and Rankine
have no zero-offset, so on-scale and difference look identical for them -
cf_attributes_for reports "temperature: unknown" rather than guessing.
CF units not in UDUNITS-2
CF defines a few units that UDUNITS-2 doesn't
(details), sourced from
cfunits. cf_unitregistry()
includes them by default:
| Unit | Behavior |
|---|---|
level, sigma_level, layer |
Dimensionless; kept only for legacy COARDS files, so using one raises a DeprecationWarning. |
practical_salinity_unit / psu |
1e-3, not 1 (CF's own FAQ is out of date here). |
decibel / dB, bel |
Plain dimensionless ratio units (see "Known limitations" above). |
sverdrup / Sv |
Sv now means sverdrup (ocean volume transport), not sievert - sievert itself still works by its full name. |
Pass cf_extensions=False to cf_unitregistry() for a registry that
matches plain UDUNITS-2 instead, without any of these additions.
Third-party notices
The UDUNITS-2 unit database this package is built on is redistributed under its own license - see THIRD_PARTY_LICENSES.md.
Metadata
Release files for pint-cf 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pint_cf-0.2.1.tar.gz | 44.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pint_cf-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 82.7 kB
Release files / pint_cf-0.2.1.tar.gz
| Download URL | pint_cf-0.2.1.tar.gz |
|---|---|
| Size | 44.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ac17b5a3bae01e88e7420fab9de7d59d12aa154497fc04739b7db4a2a9deee57
|
|
BLAKE2b-256 checksum How to use checksums |
30f284442c0904dac2829f2730b0c039d2a387066c820d7e32f19346f82579ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.
Transparency logRelease files / pint_cf-0.2.1-py3-none-any.whl
| Download URL | pint_cf-0.2.1-py3-none-any.whl |
|---|---|
| Size | 38.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2794b2e618d9bf461212a4857d818afb8d72cef57b8c4301dad4276278237c3d
|
|
BLAKE2b-256 checksum How to use checksums |
47694f63252fa93378128d61b8a9c76ec74ccdbc44446a7678a775c705cdcaf5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.
Transparency log