Fast, offline reverse geocoding for India
Project description
lakhua (Python)
Sub-millisecond reverse geocoding for India. Runs entirely in-memory — zero API calls, zero network, zero latency overhead.
Features
- 📍 converts
lat, lontocity,state, optionaldistrictandpincode - 🔢 supports direct H3 index lookup via
geocode_h3() - ↩️ parent-cell fallback (
resolution 5 → 4) when exact cell has no data - ⚡ data loaded once per process — all subsequent lookups are in-memory dict reads
- 🐛 optional debug mode traces load time and per-lookup timing
- 🔷 fully typed — dataclasses with
py.typedmarker included
Installation
pip install lakhua
Quick Start
from lakhua import geocode
result = geocode(28.6139, 77.2090)
if result:
print(result.city, result.state)
API
Top-level functions (recommended)
geocode(lat: float, lon: float, options: Optional[GeocodeOptions] = None) -> Optional[GeocodeResult]
geocode_h3(h3_index: str, options: Optional[GeocodeOptions] = None) -> Optional[GeocodeResult]
These use the internal singleton geocoder — no class instantiation needed.
GeocodeOptions
from dataclasses import dataclass
@dataclass
class GeocodeOptions:
resolution: int = 5 # H3 resolution for geocode(lat, lon)
fallback: bool = True # Walk up to parent resolution on miss
debug: bool = False # Print load and lookup timings
GeocodeResult
from dataclasses import dataclass
from typing import Optional
@dataclass(frozen=True)
class GeocodeResult:
city: str
state: str
matched_h3: str # H3 cell that matched (may be parent)
matched_resolution: int # Resolution of the matched cell
district: Optional[str] = None
pincode: Optional[str] = None
Returns None for invalid input or when no data exists for the given location.
Advanced class APIs
from lakhua import ReverseGeocoder, DataLoader
ReverseGeocoder.get_instance()
DataLoader.get_instance()
Use these only when you need explicit control — e.g. testing or custom singleton lifecycle.
Examples
Coordinate lookup
from lakhua import geocode
result = geocode(12.9716, 77.5946) # Bengaluru
if result:
print(result.city, result.state, result.pincode)
Direct H3 lookup
from lakhua import geocode_h3
result = geocode_h3("8560145bfffffff")
if result:
print(result.city)
Debug mode
from lakhua import geocode, GeocodeOptions
result = geocode(19.076, 72.8777, GeocodeOptions(debug=True))
# prints load + lookup timings to stdout
Disable fallback
from lakhua import geocode, GeocodeOptions
result = geocode(28.6139, 77.2090, GeocodeOptions(fallback=False))
# only checks resolution 5, no parent lookup
Data Source and Indexing
- Indexing system: Uber H3
- Geographic source data: OpenStreetMap data by OpenStreetMap contributors
- Distribution model: precomputed JSON stores bundled with the package
Performance
- Data is loaded into memory once on first call.
- Each lookup is a single dict read — typically < 1ms.
- With fallback enabled, up to 2 dict reads (resolution 5, then 4).
Development
# install with dev dependencies
pip install -e ".[dev]"
# run tests
pytest
# lint and format
ruff check .
ruff format .
# type check
mypy lakhua
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lakhua-1.0.1.tar.gz.
File metadata
- Download URL: lakhua-1.0.1.tar.gz
- Upload date:
- Size: 242.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2723db217d2471c845f9d8aa04c803a833f24e18d9826fc52a87f385b038e66b
|
|
| MD5 |
13016730bf77db6e4d5930bece9a49a5
|
|
| BLAKE2b-256 |
539a11f8e384dc481f4d06187b12da9a4f5765a832d6cc589cdc6bb7ac2bfc39
|
Provenance
The following attestation bundles were made for lakhua-1.0.1.tar.gz:
Publisher:
pypi-publish.yml on aialok/lakhua
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lakhua-1.0.1.tar.gz -
Subject digest:
2723db217d2471c845f9d8aa04c803a833f24e18d9826fc52a87f385b038e66b - Sigstore transparency entry: 998603378
- Sigstore integration time:
-
Permalink:
aialok/lakhua@d71d28afd1b1d85f5c1c014ef8fddd3382903af1 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/aialok
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@d71d28afd1b1d85f5c1c014ef8fddd3382903af1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file lakhua-1.0.1-py3-none-any.whl.
File metadata
- Download URL: lakhua-1.0.1-py3-none-any.whl
- Upload date:
- Size: 250.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d6d6687de9d5233c2f6f0b2ef0d38fa94a5c2d663c112085407e7d68e4ffab20
|
|
| MD5 |
70a0d5b8312f6135ebdb5ab4651966ee
|
|
| BLAKE2b-256 |
86c3e55c3c1f1a3ade0b07e1e35cdf872cfbaae7d938ca07a1fa0a3894422889
|
Provenance
The following attestation bundles were made for lakhua-1.0.1-py3-none-any.whl:
Publisher:
pypi-publish.yml on aialok/lakhua
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lakhua-1.0.1-py3-none-any.whl -
Subject digest:
d6d6687de9d5233c2f6f0b2ef0d38fa94a5c2d663c112085407e7d68e4ffab20 - Sigstore transparency entry: 998603425
- Sigstore integration time:
-
Permalink:
aialok/lakhua@d71d28afd1b1d85f5c1c014ef8fddd3382903af1 -
Branch / Tag:
refs/tags/v1.0.1 - Owner: https://github.com/aialok
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@d71d28afd1b1d85f5c1c014ef8fddd3382903af1 -
Trigger Event:
release
-
Statement type: