Skip to main content

Fast quantities (units of measurement) for Python — Rust-powered.

Project description

https://github.com/cjrh/misu/actions/workflows/ci.yml/badge.svg?branch=master https://coveralls.io/repos/github/cjrh/misu/badge.svg?branch=master https://img.shields.io/pypi/pyversions/misu.svg https://img.shields.io/github/tag/cjrh/misu.svg https://img.shields.io/pypi/v/misu.svg

misu

misu is short for “misura”, which means measurement (in Italian). misu is a package for doing calculations with in consistent units of measurement.

Install

Precompiled wheels are published to PyPI for Linux (x86_64, aarch64), macOS (x86_64, aarch64), and Windows (x64), covering Python 3.9 and later. There is nothing to compile.

uv add misu        # in a uv project
uv pip install misu
pip install misu

Demo

Most of the time you will probably work with misu interactively, and it will be most convenient to import the entire namespace:

from misu import *

mass = 100*kg
print(mass >> lb)

The symbol kg got imported from the misu package. We redefine the shift operator to perform inline conversions. The code above produces:

220.46226218487757

There are many units already defined, and it is easy to add more. Here we convert the same quantity into ounces:

print(mass >> oz)

output:

3571.4285714285716

What you see above would be useless on its own. What you really need is to be able to perform consistent calculations with quantities expressed in different, but compatible units:

mass = 10*kg + 20*lb
print(mass)

output:

19.07 kg

For addition and subtraction, misu will ensure that only consistent units can be used. Multiplication and division will produce new units:

distance = 100*metres
time = 9.2*seconds

speed = distance / time
print(speed)

output:

10.87 m/s

As before, it is trivially easy to express that quantity in different units of compatible dimensions:

print(speed >> km/hr)

output:

39.130434782608695

Introduction

misu is a package of handling physical quantities with dimensions. This means performing calculations with all the units being tracked correctly. It is possible to add kilograms per hour to ounces per minute, obtain the correct answer, and have that answer be reported in, say, pounds per week.

misu grew out of a personal need. I have used this code personally in a (chemical) engineering context for well over a year now (at time of writing, Feb 2015). Every feature has been added in response to a personal need.

Features

  • Speed optimized. misu is very fast! Heavy math code in Python is only around 5X slower when expressed with misu quantities instead of plain floats — see Performance below for measured numbers. This is much faster than other quantities packages for Python.

  • Implemented as a Rust extension module via PyO3, so the hot paths run as native code.

  • When an operation involving incompatible units is attempted, an EIncompatibleUnits exception is raised, with a clear explanation message about which units were inconsistent.

  • Decorators for functions to enforce dimensions

@dimensions(x='Length', y='Mass')
def f(x, y):
    return x/y

f(2*m, 3*kg)         # Works
f(200*feet, 3*tons)  # Works

f(2*joules, 3*kelvin)  # raises AssertionError
f(2*m, 3)              # raises AssertionError
  • An operator for easily stripping the units component to obtain a plain numerical value

mass = 100 * kg
mass_lb = mass >> lb

duty = 50 * MW
duty_BTU_hr = duty >> BTU / hr
  • An enormous amount of redundancy in the naming of various units. This means that m, metre, metres, METRE, METRES will all work. The reason for this is that from my own experience, when working interactively (e.g. in the IPython Notebook) it can be very distracting to incorrectly guess the name for a particular unit, and have to look it up. ft, foot and feet all work, m3 means m**3 and so on.

  • You can specify a reporting unit for a dimension, meaning that you could have all lengths be reported in “feet” by default for example.

  • You can specify a reporting format for a particular unit.

Performance

Two looping numerical workloads, each timed in plain Python floats and then with misu quantities (so every operation in the inner loop pays the unit-tracking cost). The benchmark lives at scripts/benchmark.py and can be re-run any time:

python scripts/benchmark.py

Representative numbers on Python 3.14, best of five runs:

Workload

float (ms)

misu (ms)

slowdown

fall_with_drag — 200k Euler steps, 1-D free-fall with quadratic drag

~19

~103

~5.2x

orbit_step — 100k 2-D Kepler steps, sqrt-heavy

~18

~91

~5.1x

Geometric mean

~5.1x

The original 5x heuristic was measured back when misu was a Cython extension; the rewrite to a Rust/PyO3 extension lands in the same ballpark, presumably because the dominant cost is the Python-call boundary around each __mul__ / __add__ rather than the unit-arithmetic itself.

There are other projects, why misu?

There are several units systems for Python, but the primary motivating use-case is that misu is written as a Rust extension module and is by far the fastest* for managing units available in Python.

*Except for ``NumericalUnits``, which is a special case

**I haven’t actually checked that this statement is true for all of them yet.

General usage

For speed-critical code, the application of unit operations can still be too slow. In these situations it is typical to first cast quantities into numerical values (doubles, say), perform the speed-critical calculations (perhaps call into a C-library), and then re-cast the result back into a quantity and return that from a function.

@dimensions(x='Length', y='Mass')
def f(x, y):
    x = x >> metre   # Converts to metres, leaving a primitive float
    y = y >> ounces  # Converts to metres, leaving a primitive float
    <code that assumes meters and ounces, returns value in BTU>
    # Convert the primitive float to BTU on the way out
    return answer * BTU

This way you can still easily wrap performance-critical calculations with robust unit-handling.

Inspiration

The inspiration for misu was Frink by Alan Eliasen. It is wonderful, but I need to work with units in the IPython Notebook, and with all my other Python code.

There are a bunch of other similar projects. I have not used any of them enough yet to provide a fair comparison:

Releasing

Publishing to PyPI is automated via GitHub Actions and PyPI trusted publishing (OIDC). No API tokens or passwords are stored anywhere — PyPI trusts the cjrh/misu repo’s release.yml workflow running in the pypi environment, and rejects everything else.

Cutting a release

The version lives in Cargo.toml. pyproject.toml declares dynamic = ["version"], so maturin reads it from the Rust crate at build time — there is only one place to edit.

Use cargo-release to bump, commit, tag, and push in one step. From a clean master:

cargo release patch --execute   # 2.0.0 → 2.0.1
cargo release minor --execute   # 2.0.0 → 2.1.0
cargo release major --execute   # 2.0.0 → 3.0.0
cargo release 2.0.5 --execute   # explicit version

Drop --execute for a dry run.

What happens automatically

cargo-release performs the following steps locally:

  1. Bumps version in Cargo.toml and updates Cargo.lock.

  2. Commits the change with the message Release <version>.

  3. Creates an annotated tag v<version>.

  4. Pushes the branch and the tag to origin.

The tag push triggers .github/workflows/release.yml, which:

  1. Builds wheels for Linux (x86_64, aarch64), macOS (x86_64, aarch64), and Windows (x64), plus an sdist. Because PyO3 is configured with abi3-py39, one wheel per (OS, arch) covers all supported Python versions.

  2. Downloads all artifacts into the release job, which runs in the pypi GitHub environment.

  3. Uploads to PyPI via pypa/gh-action-pypi-publish. Authentication happens via OIDC against the trusted-publisher configuration on PyPI; nothing else is needed.

If the build jobs succeed but the release job fails (for example, the PyPI environment was not configured), nothing is published, and the release can be retried by re-running just the failed job.

Troubleshooting

  • cargo-release refuses with “uncommitted changes” — commit or stash first; cargo-release insists on a clean tree.

  • cargo-release refuses with “not on allowed branch” — release only from master (the default allow-branch setting).

  • PyPI rejects the upload with “version already exists” — PyPI filenames are immutable; bump again.

  • Tag pushed but workflow did not run — check the tag matches the tags: '*' trigger in release.yml and that the pypi GitHub environment exists with no protection rules blocking the run.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

misu-2.0.3.tar.gz (54.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

misu-2.0.3-cp314-cp314t-win_amd64.whl (246.1 kB view details)

Uploaded CPython 3.14tWindows x86-64

misu-2.0.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (345.0 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ x86-64

misu-2.0.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (327.8 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARM64

misu-2.0.3-cp314-cp314t-macosx_11_0_arm64.whl (309.5 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

misu-2.0.3-cp314-cp314t-macosx_10_12_x86_64.whl (329.6 kB view details)

Uploaded CPython 3.14tmacOS 10.12+ x86-64

misu-2.0.3-cp39-abi3-win_amd64.whl (249.7 kB view details)

Uploaded CPython 3.9+Windows x86-64

misu-2.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (349.6 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

misu-2.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (334.9 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

misu-2.0.3-cp39-abi3-macosx_11_0_arm64.whl (316.5 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

misu-2.0.3-cp39-abi3-macosx_10_12_x86_64.whl (337.9 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file misu-2.0.3.tar.gz.

File metadata

  • Download URL: misu-2.0.3.tar.gz
  • Upload date:
  • Size: 54.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for misu-2.0.3.tar.gz
Algorithm Hash digest
SHA256 d74a29af570bd2a34b0e894a61f00118ade6a452a5c5c575f874128eaae1b02d
MD5 5d6984873905b7989e3afb7689fb6c8b
BLAKE2b-256 2a3a40976a0feafadadb43d9546027f15b68e5aca7af016741f717fbf1e49a35

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3.tar.gz:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp314-cp314t-win_amd64.whl.

File metadata

  • Download URL: misu-2.0.3-cp314-cp314t-win_amd64.whl
  • Upload date:
  • Size: 246.1 kB
  • Tags: CPython 3.14t, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for misu-2.0.3-cp314-cp314t-win_amd64.whl
Algorithm Hash digest
SHA256 7bc1adc4456a7398f664ac36078829d72a8ea1c5cb6b87633d167f234fc0b64b
MD5 65099ba7b47f85f9effe344f2f24e109
BLAKE2b-256 b3a1c116b634f47f033061427b197989a9ef9607233f8a554f6936343012071e

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp314-cp314t-win_amd64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for misu-2.0.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fbb317f288c5b06f4fc7f83e4e5bae90f513aee0aee3af5059778ebde4c59a1a
MD5 b16b394c0a33b51fb053f1fe35140102
BLAKE2b-256 e052a52a372455b2d231f2240c0089d747962a0db4a878c847db518699c34a12

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for misu-2.0.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e011094313c609669b5fc3ae2c01135e3282c72e75045cccead20789306e6652
MD5 e5ee2831c452fb105f944837685ecf6d
BLAKE2b-256 c01722a641c5b6e1fb57169872131741afc752d57e9aac14bf69c938af7f4ffe

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for misu-2.0.3-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 65e3a46bd6924f19df72bee70c076a2b3632b0c7f4e8d07f0a0754bbd76d02b7
MD5 efc0d8857a25c82ca3d33554e0937337
BLAKE2b-256 21c7edc3e52c35e12242ec037196f89394879838c902a20a822e842d7b83029a

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp314-cp314t-macosx_11_0_arm64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp314-cp314t-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for misu-2.0.3-cp314-cp314t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b80f71df2c607748f0986219d04c8eb5a458b052a882498a9262f7b20c3706bf
MD5 bc021520d2095833fa56d3a2d7024b91
BLAKE2b-256 c11c9f564d814801aeb9b711444b01ed5641f31cd3cd6712dce4729b9b596347

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp314-cp314t-macosx_10_12_x86_64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: misu-2.0.3-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 249.7 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for misu-2.0.3-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 ba3681d6ae27a0f0a3ec283022f51e15c2a1529553d504c6b5040f50619be9de
MD5 3a0f582e2aceaea5a9beb40370af9d9b
BLAKE2b-256 3a16e35cdd80392a06b091ad4ca31a525625ac53a45181a60df1207ebc5be57b

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp39-abi3-win_amd64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for misu-2.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 308c9c1aa5fab5109a28140f94c1888b219873f9d73a5e8d22ef25d2c1f0e43a
MD5 12cbca11535e0ef7c2be64c46deac3ca
BLAKE2b-256 50ef24f2dfb978ba61677f0232d8f7866bd34c871e0908eb9ef5b2da48619871

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for misu-2.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4f8c26f8df92579aed6ac20e646c42a6b61727fb50efa40a337de9a9e7bd7d16
MD5 df489b35e1ad46134d791f36122ea44c
BLAKE2b-256 c25d74a96118cdecccb6511aa8b9988b8462aa617cee41428657dce96c2ee927

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: misu-2.0.3-cp39-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 316.5 kB
  • Tags: CPython 3.9+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for misu-2.0.3-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f83e114052e8229310471f4c59435e73de19eb41df15e0c090591ded3fb88b43
MD5 1fa62f92bffb15204bfb1fee672b4c40
BLAKE2b-256 819d24222dbffa3398366af2c299b1b26be46c3b973daed146f7cb5d066ca74b

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file misu-2.0.3-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: misu-2.0.3-cp39-abi3-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 337.9 kB
  • Tags: CPython 3.9+, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for misu-2.0.3-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 1661140d2e1daf2c2669686fcd4184114e821ab1ccd6e670301085c3f0e98945
MD5 433af27162f7c3c214bbf5f079485fc9
BLAKE2b-256 b54aece880146a7b84c5cef9f98988e3e22e83fae093f45f410f31682d144b35

See more details on using hashes here.

Provenance

The following attestation bundles were made for misu-2.0.3-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on cjrh/misu

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page