Skip to main content

PyConvert

A lightweight unit and number-base conversion library for Python, with no dependencies beyond the standard library.

Tests PyPI Python versions License: MIT

Install

pip install pyconvertx

The install name and the import name differ. Install pyconvertx, import pyconvert.

import pyconvert          # not "import pyconvertx"

The name pyconvert was already taken on PyPI in 2015 by an unrelated XML/JSON library, so this project is distributed under pyconvertx. A distribution name that differs from the import name is common — pip install beautifulsoup4 gives you import bs4, and pip install pillow gives you import PIL.

Quick start

import pyconvert

pyconvert.convert(100, "km", "mi")                 # 62.13711922373339
pyconvert.convert(100, "celsius", "fahrenheit")    # 212.0
pyconvert.convert(1024, "MiB", "GiB")              # 1.0
pyconvert.convert(1, "gal_us", "L")                # 3.785411784

pyconvert.convert_base(100, 10, 2)                 # '1100100'
pyconvert.convert_base("10101111", 2, 16)          # 'AF'
pyconvert.convert_base("FF", 16, 10)               # '255'
pyconvert.convert_base(1000, 10, 36)               # 'RS'

No setup, no classes to instantiate, no unit objects to construct.

Unit conversion

convert(value, from_unit, to_unit) -> float

There is no category argument. Every unit symbol is unique across the whole library, so the category is looked up from the symbols you give. A consequence worth having: mixing categories is an error rather than a plausible-looking wrong number.

>>> pyconvert.convert(1, "kg", "m")
IncompatibleUnitsError: cannot convert 'kg' to 'm': 'kg' measures mass, 'm' measures length

Supported units

182 units across 15 categories. Factors are stored relative to each category's base unit, so every pair within a category works, including combinations nobody thought to write down (furlong to nmi, therm to eV).

Category Base Units Count
Length m angstrom, au, chain, cm, dam, dm, fathom, ft, furlong, hm, in, km, ly, m, mi, mm, nm, nmi, pc, pm, rod, thou, um, yd 24
Mass kg carat, g, grain, kg, lb, m_e, m_earth, m_sun, mg, oz, quintal, st, t, ton_uk, ton_us, u, ug 17
Speed m/s c, cm/s, ft/s, km/h, kn, m/s, mm/s, mph 8
Area m2 ac, are, cm2, ft2, ha, in2, km2, m2, mi2, mm2, yd2 11
Volume m3 bbl, cL, cm3, cup_us, dL, floz_imp, floz_us, ft3, gal_imp, gal_us, in3, kL, km3, L, m3, mL, mm3, pt_imp, pt_us, qt_imp, qt_us, tbsp_us, tsp_us, uL, yd3 25
Energy J BTU, cal, cal_it, erg, eV, ft_lbf, GeV, GJ, J, kcal, keV, kJ, kWh, MeV, MJ, mJ, MWh, therm, Wh 19
Power W BTU/h, GW, hp, hp_metric, kW, MW, mW, TW, uW, W 10
Temperature kelvin celsius, fahrenheit, kelvin, rankine 4
Time s d, fortnight, h, min, ms, ns, ps, s, us, week, yr 11
Pressure Pa atm, bar, GPa, hPa, inHg, kPa, mbar, mmHg, MPa, Pa, psi, torr 12
Frequency Hz GHz, Hz, kHz, MHz, mHz, rpm, THz 7
Digital storage B B, bit, GB, Gbit, GiB, kB, kbit, KiB, MB, Mbit, MiB, PB, PiB, TB, TiB 15
Angle rad arcmin, arcsec, deg, grad, mrad, rad, turn 7
Electric current A A, kA, mA, nA, pA, uA 6
Electric potential V kV, MV, mV, nV, uV, V 6

Alternative spellings

Long names, plurals and typeable forms of awkward symbols all resolve to the same unit — 390 aliases in total:

pyconvert.convert(1, "kilometre", "mile")   # British or American spelling
pyconvert.convert(1, "meters", "feet")      # plurals
pyconvert.convert(5000, "m2", "hectare")    # ASCII for m^2
pyconvert.convert(5000, "m²", "hectare")    # or the real character
pyconvert.convert(100, "degC", "degF")      # ASCII for °C
pyconvert.convert(100, "°C", "°F")          # or the real character
pyconvert.convert(500, "μs", "ms")          # either Unicode micro sign

That last one matters more than it looks. The micro prefix is written two ways that are visually identical: MICRO SIGN (U+00B5), which is what a Mac's Option-M produces, and GREEK SMALL LETTER MU (U+03BC). They are different characters, so a dictionary treats them as different keys. Both map to the ASCII spelling (us, um, ug, uA, uV, uW, uL), as does the plain ASCII form.

Lookup is case-sensitive

It has to be. These pairs are standard notation and differ only by case:

mW milliwatt MW megawatt factor of 10⁹
mHz millihertz MHz megahertz factor of 10⁹
mV millivolt MV megavolt factor of 10⁹
kB kilobyte (1000) KiB kibibyte (1024) 2.4% apart
ps picosecond PS metric horsepower different categories

Folding case would make those indistinguishable. Wrong case is caught and suggested back instead:

>>> pyconvert.convert(1, "KM", "mi")
UnknownUnitError: unknown unit 'KM' (did you mean 'km'?)

Units this library refuses on purpose

Some spellings have more than one real meaning, and resolving them to one arbitrary choice would return a confidently wrong number. These raise with the fix in the message rather than guessing:

Spelling Why, and what to use
C use 'celsius' or 'degC' (bare 'C' is the SI symbol for coulomb)
F use 'fahrenheit' or 'degF' (bare 'F' is the SI symbol for farad)
R use 'rankine' or 'degR' (bare 'R' is the symbol for roentgen)
b use 'bit' or 'B' (byte) -- 'b' and 'B' differ only by case
cal_cap use 'kcal' for the food Calorie, or 'cal' for the gram calorie
fl_ounce use 'floz_us' or 'floz_imp'
gb use 'Gbit' (109 bits) or 'GB' (109 bytes)
hp_imp use 'hp' (mechanical) or 'hp_metric' (PS)
kb use 'kbit' (1000 bits) or 'kB' (1000 bytes)
mb use 'Mbit' (106 bits) or 'MB' (106 bytes)
pt 'pt' is both point and pint: use 'pt_us' or 'pt_imp' for pints
tb use 'TB' (1012 bytes) or 'TiB' (240 bytes)
ton 'ton' means three different masses: use 't' (tonne, 1000 kg), 'ton_us' (short, 907.18474 kg) or 'ton_uk' (long, 1016.0469088 kg)
tons see 'ton': use 't', 'ton_us' or 'ton_uk'

C, F and R are also kept free so that charge, capacitance and radiation can be added later without a breaking change.

One default is chosen: bare gal, gallon, quart, pint, cup, floz, tbsp and tsp mean the US measures. The imperial ones are available explicitly as gal_imp, qt_imp, pt_imp and floz_imp.

Where a unit has competing definitions, the one picked is documented:

Unit This library uses Also available
cal thermochemical, 4.184 J exactly cal_it (4.1868 J)
hp mechanical, 745.6998… W hp_metric / PS (735.49875 W)
BTU International Table, 1055.05585262 J —
yr Julian year, exactly 365.25 days —
t tonne, 1000 kg ton_us, ton_uk

Number bases

convert_base(number, from_base, to_base, precision=16) -> str

Bases 2 to 36. Input may be an int or a str, in either case, with underscores allowed as separators. Output digits are always uppercase.

pyconvert.convert_base("ff", 16, 2)          # '11111111'
pyconvert.convert_base("1111_1111", 2, 16)   # 'FF'
pyconvert.convert_base(-255, 10, 16)         # '-FF'
pyconvert.convert_base(1100100, 2, 10)       # '100'  (an int is read as its digits)

Fractional parts are converted exactly where the result terminates:

pyconvert.convert_base("0.5", 10, 2)         # '0.1'
pyconvert.convert_base("A.8", 16, 10)        # '10.5'
pyconvert.convert_base("0.1", 10, 2)         # '0.0001100110011001'

That last result is truncated, not wrong — one tenth has no finite binary form, so it runs to precision digits and stops. Pass precision to change that.

The result is always a string, including when the target base is 10. Once 'AF' is a string, returning an int for base 10 alone would make the return type depend on an argument's value. Call int(result) when you want a number back.

Accuracy

Factors that are exact by international definition are stored as exact rationals and rounded to float once, rather than being computed in floating point. The difference is small but real: 231 * 0.0254 ** 3 gives 0.0037854117839999997, three roundings away from the correctly rounded 0.003785411784.

Temperature is computed in exact rational arithmetic, because it is the one category with an offset, and 5/9 has no finite binary form. In plain floats, 100 °C → °F returns 211.99999999999997. Here:

pyconvert.convert(100, "celsius", "fahrenheit")    # 212.0  exactly
pyconvert.convert(0,   "celsius", "fahrenheit")    # 32.0   exactly
pyconvert.convert(-40, "celsius", "fahrenheit")    # -40.0  exactly
pyconvert.convert(0,   "kelvin",  "fahrenheit")    # -459.67 exactly

Everything else uses a single float ratio, which is about ten times faster and is what nearly every conversion needs. Results are ordinary IEEE-754 doubles, so between two non-base units you can still see a last-digit artefact: convert(1, "gal_imp", "L") is 4.5460899999999995 rather than 4.54609. Conversions to a category's base unit are exact.

Errors

Everything this library raises derives from PyConvertError, so one except catches all of it. Each error also subclasses the builtin you would expect, so existing except KeyError or except ValueError code keeps working.

PyConvertError
├── UnknownUnitError        (also KeyError)    unit not in the registry
├── UnknownCategoryError    (also KeyError)    no such category
├── IncompatibleUnitsError                     the two units measure different things
├── InvalidBaseError        (also ValueError)  base outside 2-36
├── InvalidDigitError       (also ValueError)  digit invalid for its base
└── RegistryError           (also RuntimeError) the registry itself is inconsistent

RegistryError is raised at import time, never from a call. It means two categories claim the same symbol, or an alias points at a unit that does not exist — a bug in the library, not in your input.

Introspection

pyconvert.list_categories()          # ['angle', 'area', 'current', ...]
pyconvert.list_units("temperature")  # ['celsius', 'fahrenheit', 'kelvin', 'rankine']
pyconvert.list_units()               # all 182 canonical symbols
pyconvert.category_of("psi")         # 'pressure'
pyconvert.base_unit("pressure")      # 'Pa'
pyconvert.is_convertible("km", "kg") # False
pyconvert.convert_all([0, 100], "celsius", "fahrenheit")   # [32.0, 212.0]

Requirements

Python 3.9 or newer. No third-party dependencies.

Development

git clone https://github.com/cobrapy-x/pyconvert-package.git
cd pyconvert-package
pip install -e ".[dev]"

pytest          # 1072 tests, including the docstring examples
ruff check .

See CONTRIBUTING.md for how to add a unit, and the invariants the test suite enforces.

License

MIT — see LICENSE.

Metadata

Release files for pyconvertx 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyconvertx 1.0.0
File Size Uploaded
pyconvertx-1.0.0.tar.gz 45.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyconvertx 1.0.0
File Interpreter ABI Platform
pyconvertx-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 70.9 kB

Release files / pyconvertx-1.0.0.tar.gz

Download URL pyconvertx-1.0.0.tar.gz
Size 45.0 kB
Tags Source
SHA-256 checksum
How to use checksums
9c95c26969b0745a30050e7bf10f74d35cbba1754736b4702d4a13b8ccf89db5
BLAKE2b-256 checksum
How to use checksums
915edc4d4b4d4616bc6dcade4246691de1d884965bad7b2e5357f61ffc56e4f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 11, 2026.

Transparency log

Release files / pyconvertx-1.0.0-py3-none-any.whl

Download URL pyconvertx-1.0.0-py3-none-any.whl
Size 25.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3d330cd5996402ded9428e8e4fafb79cd85d96517344598fcb1735a13acec8cd
BLAKE2b-256 checksum
How to use checksums
1e222c9837bb0450116ff966f034494c3c5bedc187e4920faa82e934558f09f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page