| name | pint-units |
| description | Handle engineering units with automatic conversion and dimensional analysis |
| category | packages |
| domain | general |
| complexity | basic |
| dependencies | ["pint"] |
Pint Units Skill
Overview
Pint is a Python package for handling physical quantities with units. It provides:
- Automatic unit conversions
- Dimensional analysis and consistency checking
- Unit-aware arithmetic operations
- Integration with NumPy arrays
- Support for custom unit definitions
- Temperature conversions (including offset units)
- Scientific notation and formatting
Pint eliminates unit conversion errors and ensures dimensional consistency in engineering calculations, making it essential for any technical work involving physical quantities.
Installation
pip install pint
For integration with NumPy and Pandas:
pip install pint[numpy]
Basic Usage
Creating Quantities
A quantity in Pint consists of a magnitude (number) and a unit.
from pint import UnitRegistry
ureg = UnitRegistry()
distance = 100 * ureg.meter
time = 5 * ureg.second
pressure = 50 * ureg.psi
flow_rate = ureg('250 gallons/minute')
temperature = ureg('75 degF')
viscosity = ureg('1.5 centipoise')
print(f"Distance magnitude: {distance.magnitude}")
print(f"Distance units: {distance.units}")
Unit Conversions
Convert between compatible units automatically:
distance = 100 * ureg.meter
print(distance.to('feet'))
print(distance.to('kilometer'))
pressure = 100 * ureg.psi
print(pressure.to('bar'))
print(pressure.to('pascal'))
flow = 500 * ureg.gallons / ureg.minute
print(flow.to('liter/second'))
print(flow.to('m**3/hour'))
temp = 75 * ureg.degF
print(temp.to('degC'))
print(temp.to('kelvin'))
Dimensional Analysis
Pint ensures dimensional consistency in calculations:
distance = 100 * ureg.meter
time = 5 * ureg.second
velocity = distance / time
print(velocity)
mass = 10 * ureg.kg
acceleration = 9.81 * ureg.meter / ureg.second**2
force = mass * acceleration
print(force)
print(force.to('newton'))
try:
invalid = (100 * ureg.meter) + (50 * ureg.second)
except Exception as e:
print(f"Error: Cannot add length and time")
total_distance = (100 * ureg.meter) + (50 * ureg.feet)
print(total_distance)
Unit-Aware Calculations
Fluid Flow Calculations
velocity = 3.5 * ureg.meter / ureg.second
diameter = 150 * ureg.millimeter
area = 3.14159 * (diameter/2)**2
flow_rate = velocity * area
print(flow_rate.to('liter/second'))
print(flow_rate.to('gpm'))
density = 998 * ureg.kg / ureg.meter**3
viscosity = 1.0 * ureg.centipoise
Re = (density * velocity * diameter) / viscosity
print(Re.to_base_units())
Pump Power Calculations
flow_rate = 100 * ureg.meter**3 / ureg.hour
head = 50 * ureg.meter
density = 1000 * ureg.kg / ureg.meter**3
gravity = 9.81 * ureg.meter / ureg.second**2
hydraulic_power = density * gravity * flow_rate * head
print(hydraulic_power.to('kilowatt'))
print(hydraulic_power.to('horsepower'))
efficiency = 0.75 * ureg.dimensionless
shaft_power = hydraulic_power / efficiency
print(shaft_power.to('kilowatt'))
Pressure Drop Calculations
friction_factor = 0.018 * ureg.dimensionless
length = 100 * ureg.meter
diameter = 0.15 * ureg.meter
velocity = 2.5 * ureg.meter / ureg.second
density = 1000 * ureg.kg / ureg.meter**3
pressure_drop = friction_factor * (length/diameter) * (density * velocity**2 / 2)
print(pressure_drop.to('pascal'))
print(pressure_drop.to('psi'))
print(pressure_drop.to('bar'))
head_loss = pressure_drop / (density * gravity)
print(head_loss.to('meter'))
print(head_loss.to('feet'))
Working with Arrays
Pint integrates seamlessly with NumPy for array operations:
import numpy as np
from pint import UnitRegistry
ureg = UnitRegistry()
flow_rates = np.array([50, 75, 100, 125, 150]) * ureg.gpm
heads = np.array([80, 75, 65, 50, 30]) * ureg.meter
powers = (flow_rates * heads * ureg.kg/ureg.meter**3 * 9.81*ureg.meter/ureg.second**2)
print(powers.to('kilowatt'))
mean_flow = np.mean(flow_rates)
std_flow = np.std(flow_rates)
print(f"Mean flow: {mean_flow.to('liter/minute'):.1f}")
print(f"Std dev: {std_flow.to('liter/minute'):.1f}")
target_head = 70 * ureg.meter
target_flow = np.interp(target_head.magnitude, heads[::-1].magnitude,
flow_rates[::-1].magnitude) * ureg.gpm
print(f"Flow at {target_head}: {target_flow.to('m**3/hour'):.1f}")
Custom Unit Definitions
Define domain-specific units:
ureg.define('barrel_oil = 42 * gallon = bbl')
ureg.define('standard_cubic_foot = foot**3 = scf')
ureg.define('darcy = centipoise * centimeter**2 / (second * atmosphere) = D')
oil_volume = 1000 * ureg.barrel_oil
print(oil_volume.to('gallon'))
print(oil_volume.to('liter'))
gas_flow = 5000 * ureg.standard_cubic_foot / ureg.day
print(gas_flow.to('m**3/hour'))
permeability = 100 * ureg.darcy
print(permeability.to_base_units())
Context Managers for Unit Systems
Switch between unit systems easily:
from pint import UnitRegistry
ureg = UnitRegistry()
length = 100 * ureg.meter
mass = 50 * ureg.kg
print(f"Length: {length}")
print(f"Mass: {mass}")
with ureg.context('US'):
print(f"Length: {length.to('feet')}")
print(f"Mass: {mass.to('pound')}")
with ureg.context('imperial'):
print(f"Length: {length.to('yard')}")
Temperature Conversions
Handle absolute and relative temperature correctly:
temp1 = 25 * ureg.degC
temp2 = temp1.to('degF')
print(temp2)
temp3 = 300 * ureg.kelvin
print(temp3.to('degC'))
temp_rise = ureg.Quantity(20, ureg.delta_degC)
print(temp_rise.to(ureg.delta_degF))
mass = 10 * ureg.kg
specific_heat = 4.18 * ureg.kJ / (ureg.kg * ureg.kelvin)
temp_change = 50 * ureg.delta_degC
heat = mass * specific_heat * temp_change
print(heat.to('kJ'))
print(heat.to('BTU'))
Formatting and Display
Control how quantities are displayed:
pressure = 150000 * ureg.pascal
print(pressure)
print(f"{pressure:~}")
print(f"{pressure:.2f}")
print(f"{pressure:~.2e}")
print(f"{pressure:~P}")
print(f"{pressure.to('bar'):.3f~P}")
Common Engineering Unit Conversions
Pressure
pressure = 100 * ureg.psi
print(pressure.to('bar'))
print(pressure.to('kPa'))
print(pressure.to('MPa'))
print(pressure.to('atm'))
print(pressure.to('mmHg'))
print(pressure.to('inch_H2O'))
Flow Rate
flow = 100 * ureg.gpm
print(flow.to('liter/minute'))
print(flow.to('m**3/hour'))
print(flow.to('ft**3/second'))
print(flow.to('barrel_oil/day'))
Viscosity
mu = 1.0 * ureg.centipoise
print(mu.to('pascal*second'))
print(mu.to('lbf*second/ft**2'))
nu = 1.0 * ureg.centistokes
print(nu.to('m**2/second'))
print(nu.to('ft**2/second'))
Energy and Power
energy = 100 * ureg.kWh
print(energy.to('MJ'))
print(energy.to('BTU'))
print(energy.to('therm'))
power = 50 * ureg.horsepower
print(power.to('kilowatt'))
print(power.to('BTU/hour'))
Mass Flow Rate
mass_flow = 1000 * ureg.kg / ureg.hour
print(mass_flow.to('lb/minute'))
print(mass_flow.to('ton/day'))
print(mass_flow.to('g/second'))
Best Practices
- Create UnitRegistry Once: Define
ureg = UnitRegistry() at module level, not inside functions
- Use Base Units for Storage: Store values in consistent base units (SI) in databases
- Validate Input Units: Always check that input quantities have expected dimensionality
- Handle Dimensionless Quantities: Use
ureg.dimensionless for unitless ratios
- Convert at Boundaries: Convert to display units only when presenting results
- Check Compatibility: Use
quantity.check(dimension) to verify dimensional consistency
- Be Explicit: Use explicit unit definitions rather than assuming defaults
- Temperature Care: Use
delta_ prefix for temperature differences vs absolute temperatures
Dimensional Consistency Checking
def calculate_reynolds_number(velocity, diameter, density, viscosity):
"""
Calculate Reynolds number with automatic dimensional checking.
Re = ρVD/μ (dimensionless)
"""
Re = (density * velocity * diameter) / viscosity
assert Re.dimensionality == ureg.dimensionless.dimensionality
return Re.to_base_units().magnitude
rho = 1000 * ureg.kg / ureg.meter**3
V = 2.5 * ureg.meter / ureg.second
D = 0.15 * ureg.meter
mu = 1e-3 * ureg.pascal * ureg.second
Re = calculate_reynolds_number(V, D, rho, mu)
print(f"Reynolds number: {Re:.0f}")
try:
Re_wrong = calculate_reynolds_number(V, D, rho, rho)
except Exception as e:
print("Error: Dimensional inconsistency detected")
Integration with Engineering Workflows
Example: Pump Performance Curve
import numpy as np
from pint import UnitRegistry
ureg = UnitRegistry()
def pump_curve(flow_rates, coefficients):
"""
Calculate pump head from flow rate using curve fit.
H = H0 - A*Q - B*Q²
Parameters
----------
flow_rates : Quantity array
Flow rates with units
coefficients : dict
'H0', 'A', 'B' with appropriate units
Returns
-------
heads : Quantity array
Pump heads with units
"""
H0 = coefficients['H0']
A = coefficients['A']
B = coefficients['B']
heads = H0 - A * flow_rates - B * flow_rates**2
return heads
coeffs = {
'H0': 80 * ureg.meter,
'A': 200 * ureg.meter / (ureg.meter**3/ureg.second),
'B': 3000 * ureg.meter / (ureg.meter**3/ureg.second)**2
}
Q = np.linspace(0, 0.1, 11) * ureg.meter**3 / ureg.second
H = pump_curve(Q, coeffs)
print("Flow (GPM) Head (ft) Head (m)")
print("-" * 40)
for q, h in zip(Q, H):
print(f"{q.to('gpm'):8.0f~P} {h.to('feet'):8.1f~P} {h.to('meter'):7.1f~P}")
Troubleshooting
Issue: DimensionalityError
Cause: Attempting to add/compare quantities with incompatible units
Solution: Check that all terms have the same dimensionality, or convert explicitly
Issue: UndefinedUnitError
Cause: Using a unit that's not defined in the registry
Solution: Define custom units using ureg.define() or check spelling
Issue: Offset units (temperature) errors
Cause: Mixing absolute and relative temperature units
Solution: Use delta_degC for temperature differences, plain degC for absolute
Issue: Lost units in calculations
Cause: Using .magnitude too early in calculations
Solution: Keep quantities as Pint objects until final output
Quick Reference Card
Common Units
| Quantity | Units |
|---|
| Length | meter, foot, inch, mile, kilometer |
| Area | meter2, foot2, acre, hectare |
| Volume | liter, gallon, barrel_oil, ft3, m3 |
| Mass | kilogram, pound, ton, tonne |
| Time | second, minute, hour, day |
| Velocity | meter/second, ft/second, mph, kph |
| Flow (Vol) | m3/hour, gpm, liter/minute, ft3/second |
| Flow (Mass) | kg/second, lb/minute, ton/hour |
| Pressure | pascal, bar, psi, atm, mmHg |
| Force | newton, lbf, kgf |
| Power | watt, horsepower, BTU/hour |
| Energy | joule, kWh, BTU, calorie |
| Temperature | degC, degF, kelvin, rankine |
| Viscosity (dyn) | pascal*second, poise, centipoise |
| Viscosity (kin) | m**2/second, stokes, centistokes |
Quick Conversions
Q = 100 * ureg.gpm
Q.to('liter/minute')
Q.to_base_units()
Q.to_compact()
Q.dimensionality
Q.check('[volume]/[time]')
Q.magnitude
Q.units
References
Further Reading
- NIST Special Publication 811: Guide for the Use of the International System of Units (SI)
- ISO 80000: Quantities and units
- API Standards for petroleum industry units
- ASME standards for engineering calculations