geors
Rust-powered drop-in replacement for geopy.
Replaces every compute-bound function in geopy with a Rust implementation using Karney's geodesic algorithm via geographiclib-rs. I/O-bound operations (geocoding, rate limiting) forward transparently to geopy.
Performance
| Operation | geopy | geors (Rust) | Speedup |
|---|---|---|---|
| Geodesic distance (scalar) | 62.5 us | 0.5 us | 125x |
| Great-circle distance | 3.1 us | 0.1 us | 31x |
| Full inverse (azimuths, scales) | 42.1 us | 0.8 us | 52x |
| Direct problem | 10.8 us | 0.6 us | 18x |
| Batch geodesic (1K points) | 59.2 ms | 0.06 ms | 1,063x |
| Batch geodesic (10K points) | 589 ms | 0.29 ms | 2,078x |
| Batch geodesic (1M points) | ~59 sec | 23.8 ms | ~2,500x |
Batch throughput: 42 million point-pairs/sec (rayon-parallel).
Verification
Verified to sub-nanometer precision against geographiclib and geopy:
- 10,000 Karney GeodTest cases -- max distance error: 7.5e-9 m (~7 nanometers), 0 cases >1mm
- 15 real-world city pairs -- max error: 9.3e-10 m (<1 nanometer)
- 13 edge cases -- identical points, poles, antipodal, antimeridian, near-antipodal (Vincenty failure cases) -- all exact match
- 1,000 random direct/inverse roundtrips -- max error: 5.6e-9 m
- 1,000 random cross-checks vs geopy -- max error: 5.6e-9 m
- Batch vs scalar consistency -- exact match (0.0 m difference)
pytest tests/test_python_compat.py -v # 57 tests
python tests/verify_accuracy.py # 37/37 comprehensive checks
python tests/bench_distance.py # full benchmark suite
Installation
pip install geors
Usage
Drop-in replacement
# Before
from geopy.distance import geodesic, great_circle
# After (same API, 125x faster)
from geors.distance import geodesic, great_circle
Distance calculations
from geors.distance import geodesic, great_circle
# Geodesic (ellipsoidal, Karney's algorithm)
d = geodesic((40.7128, -74.0060), (51.5074, -0.1278))
print(d.km) # 5570.248...
print(d.miles) # 3461.358...
print(d.meters) # 5570248.4...
print(d.feet) # 18274764.0...
print(d.nautical) # 3007.6...
# Great circle (spherical, Haversine)
d = great_circle((40.7128, -74.0060), (51.5074, -0.1278))
print(d.km) # 5564.847...
Low-level functions
from geors._geors import distance, geodesic
# Scalar
meters = distance.geodesic_distance(40.7128, -74.0060, 51.5074, -0.1278)
# Full inverse (returns dict with s12, azi1, azi2, a12, ...)
result = distance.geodesic_inverse(40.7128, -74.0060, 51.5074, -0.1278)
# Direct problem (start + bearing + distance -> endpoint)
result = geodesic.direct(40.7128, -74.0060, 51.37, 5_554_000.0)
# Destination
lat2, lon2 = distance.geodesic_destination(40.7128, -74.0060, 51.37, 5_554_000.0)
Batch operations (numpy arrays, rayon-parallel)
import numpy as np
from geors._geors import distance
lat1 = np.random.uniform(-90, 90, 1_000_000)
lon1 = np.random.uniform(-180, 180, 1_000_000)
lat2 = np.random.uniform(-90, 90, 1_000_000)
lon2 = np.random.uniform(-180, 180, 1_000_000)
# Returns numpy array, computed in parallel across all cores
distances = distance.geodesic_distance_batch(lat1, lon1, lat2, lon2)
distances_gc = distance.great_circle_distance_batch(lat1, lon1, lat2, lon2)
Geocoding (forwards to geopy)
# Geocoding is I/O-bound, so we forward to geopy transparently
from geors.geocoders import Nominatim
geolocator = Nominatim(user_agent="my-app")
location = geolocator.geocode("New York City")
print(location.latitude, location.longitude)
What's Rust, what's forwarded
| Component | Implementation | Why |
|---|---|---|
geors.distance.geodesic |
Rust (geographiclib-rs) | CPU-bound: Karney's iterative algorithm |
geors.distance.great_circle |
Rust | CPU-bound: Haversine trig |
geodesic_distance_batch |
Rust + rayon | Parallel array processing |
geors.geocoders.* |
Forwards to geopy | I/O-bound: HTTP API calls |
geors.extra.rate_limiter |
Forwards to geopy | I/O-bound: sleep/retry logic |
| Unit conversions | Rust | Simple arithmetic, zero overhead |
Architecture
geors/
crates/
geo-math/ # High-precision math (trig in degrees, error-free sums, Accumulator)
geors/ # Core library (geodesic, great-circle, polygon area, constants)
src/ # PyO3 bindings (py_distance, py_geodesic, py_units)
python/geors/ # Drop-in Python wrapper (Distance class, geocoder forwarding)
Built with PyO3 + maturin. Wheels for Linux, macOS, and Windows.
License
MIT
Release files for geors 0.1.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 | |
|---|---|---|---|
| geors-0.1.1.tar.gz | 37.6 kB | Details |
Built distributions (wheels)
Total release size: 4.1 MB
Release files / geors-0.1.1.tar.gz
| Download URL | geors-0.1.1.tar.gz |
|---|---|
| Size | 37.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
aa93f8712ef20720a1e4de8931a856cb22a71c1a535de3f49757a8c8fe18de1d
|
|
BLAKE2b-256 checksum How to use checksums |
a5570bf746b651d533a7159b38843eec0c9e5239cb9bfb5adc2c08b7382ab71d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | geors-0.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 398.3 kB |
| Tags | CPython 3.13 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
b5f01eb0d5243e5cdb877bbbf4b2a3720ceecb6ffb00b096227221e10947b676
|
|
BLAKE2b-256 checksum How to use checksums |
8c9f5b2d3c20c4ffaf8cef9322b5032926cad1f2a4b266401bcab14f6eaa31a1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | geors-0.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 386.0 kB |
| Tags | CPython 3.13 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
680deb49fa5988dbd6f0b036432f370c1b0714d567d417b4b21b61846ee0f9ac
|
|
BLAKE2b-256 checksum How to use checksums |
ffbf62d12ed1dd295a898879321416fcc1c94b51e71464a49b22257537c43403
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp312-cp312-win_amd64.whl
| Download URL | geors-0.1.1-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 223.5 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
17d4a8321042d571b2d27e6c43150b3220d8a6609f9c122b101ff8b4f4e71064
|
|
BLAKE2b-256 checksum How to use checksums |
3d45cfb87508113c365ba87bd78353b18d6b438c7a11ccecbf8ee1ebeecc5498
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | geors-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 399.1 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
8977622fcf65d501d9f2e53b8842079e1e27d748c6cb6dd69da0cb7761470e3b
|
|
BLAKE2b-256 checksum How to use checksums |
544170d7895cfb0505f5f9c54d55531aa49533b85758201056f803d3e5a83b9c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | geors-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 386.4 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
596c24dc3f9ebccda24c5121497d1f70cf13df0a5599e5d45b9f241c652ddba5
|
|
BLAKE2b-256 checksum How to use checksums |
ae95cc53aff773e1341c86597db317bf001c2ee3ce94555944492c99176fb24c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | geors-0.1.1-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 335.9 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
fcd38a668218def36688d1a8740284e34c7e89636b1f75e26d91a453d804d27e
|
|
BLAKE2b-256 checksum How to use checksums |
270a771addb345a7a48e79bbfd1018f904afb89191010e51788924b12393594c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp312-cp312-macosx_10_12_x86_64.whl
| Download URL | geors-0.1.1-cp312-cp312-macosx_10_12_x86_64.whl |
|---|---|
| Size | 342.7 kB |
| Tags | CPython 3.12 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
09bf5ec9e5bfd07db93cec1ece357340f0a208c579bdf42624ae7a395dc36521
|
|
BLAKE2b-256 checksum How to use checksums |
0ef896764a0aaac0477223d80dc8472bc37e2cb77fcc4262887a0f4b1037436a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | geors-0.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 398.9 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
d37f7cb43efc34606ee7698739a4ca0e49b2bc01398e1fe640224eb1c4fd70f8
|
|
BLAKE2b-256 checksum How to use checksums |
b1a84fc593c4a71a54bb92a541b3509dc0b4cd9f047d56f690e0b5440fff9f80
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | geors-0.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 386.4 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
91f05d79d276018761ef50d26c17a49d6b592ddfb47ba76c2d671f3d119ce406
|
|
BLAKE2b-256 checksum How to use checksums |
069aecaf2f4d9f524ff427459c43b4150a7564fd2afc83a05215c33cef40c4ac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | geors-0.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 398.9 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 |
|
SHA-256 checksum How to use checksums |
7452906c64d7085d85e2f304b60de314b37ddbb2747cb99a61da17a288ead34e
|
|
BLAKE2b-256 checksum How to use checksums |
40083111885aa6eec9d74eaeb17f80c01230530a0de3c09c9cb7c33442679c10
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|
Release files / geors-0.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | geors-0.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 386.4 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ ARM64 |
|
SHA-256 checksum How to use checksums |
7282e618e50da8788deef31866090bf3ab15eed6a042037aac2feeb1bbe770e9
|
|
BLAKE2b-256 checksum How to use checksums |
0c35c5caf818e9aebc03a580fb74ffc5e0933b767a4508286bcef535913000a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
maturin/1.12.6
|