Skip to main content

Offline postal-code / geocode lookup — O(1) & O(log N) indexed, TB/ZB scale ready

Project description

zipfinder

PyPI version Python versions License: MIT GitHub stars

Upgraded from bd-geocode-offline? See the migration guide below.

Complete offline GeoNames postal-code / geocode database for Python. Works 100 % offline no internet connection required.

Features

  • 1.8 million records 121 countries, complete GeoNames dataset
  • O(1) lookups hash-indexed, constant time regardless of dataset size
  • O(log N) prefix search bisect-based, no full-table scans ever
  • Spatial radius search geo-grid index, O(C + Klog K)
  • TB / ZB scale optional SQLite mode for datasets that exceed RAM
  • Zero dependencies Python standard library only
  • Fully embedded all data ships inside the package
  • Backward compatible old bd-geocode-offline imports still work

Installation

pip install zipfinder

To upgrade from the old package:

pip install zipfinder
pip uninstall bd-geocode-offline   # optional cleanup

Quick Start

from zip_finder import lookup_zip, lookup_all_zips, search_zip, find_nearby_zips

# Exact lookup  O(1)
record = lookup_zip("94107", country="US")
print(record["city"])          # San Francisco
print(record["latitude"])      # 37.7647

# Lookup without country  returns first match across all countries
record = lookup_zip("94107")

# All countries sharing the same code  O(1)
all_matches = lookup_all_zips("94107")
for r in all_matches:
    print(r["country_code"], r["city"])

# Prefix search by zip or city  O(log N + K)
results = search_zip("Lon", country="GB", limit=5)
for r in results:
    print(r["postal_code"], r["city"])

# Nearby zip codes by coordinates  O(C + Klog K)
nearby = find_nearby_zips(37.7749, -122.4194, radius_km=10, limit=5)
for r in nearby:
    print(r["city"], r["distance_km"], "km")

API Reference

Function Description Time Complexity
lookup_zip(code, country=None) Single zip lookup, returns one record or None O(1)
lookup_all_zips(code, country=None) All records for a zip across countries O(1)
search_zip(query, country=None, limit=10) Prefix search by zip or city name O(log N + K)
find_nearby_zips(lat, lon, radius_km=10, limit=10) Radius search by coordinates O(C + Klog K)
get_db_stats() Total records and country count O(1)
list_countries() Sorted list of all ISO-3166 country codes O(1)
get_database(use_sqlite=False) Access the raw database singleton

Record format

Every returned dict contains:

{
    "postal_code":   "94107",
    "city":          "San Francisco",
    "state":         "California",
    "state_code":    "CA",
    "country_code":  "US",
    "latitude":      37.7647,
    "longitude":     -122.4194,
    "accuracy":      4
}

Results from find_nearby_zips also include a "distance_km" field.

Advanced Usage

Database statistics

from zip_finder import get_db_stats, list_countries

stats = get_db_stats()
print(f"Records : {stats['total_records']:,}")   # 1,826,607
print(f"Countries: {stats['countries']}")        # 121

countries = list_countries()
print(countries[:5])   # ['AD', 'AE', 'AI', 'AL', 'AR']

TB / ZB scale SQLite mode

For datasets that exceed available RAM:

from zip_finder import get_database

db = get_database(use_sqlite=True)
record = db.lookup_zip("94107", country="US")

Migrating from bd-geocode-offline

zipfinder 2.0.0 is a drop-in upgrade. Old function names still work as deprecated aliases, so no code change is required immediately. However, the new names are recommended:

Old name (still works) New name (recommended)
get(code, country) lookup_zip(code, country)
get_all(code) lookup_all_zips(code)
search(query) search_zip(query)
find_nearby(lat, lon) find_nearby_zips(lat, lon)
get_stats() get_db_stats()
get_countries() list_countries()
# Install the new package
pip install zipfinder

# Old import path still works (backward-compatible alias)
from zip_finder import get

# New recommended API
from zip_finder import lookup_zip

Contributing

  1. Fork https://github.com/karthikbd/zipfinder
  2. Create a branch: git checkout -b feature/my-feature
  3. Run tests: python -m pytest tests/ -v
  4. Push and open a Pull Request

License

MIT Karthikeyan Balasundaram


Previously published as bd-geocode-offline 1.0.0.

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

zipfinder-2.0.0.tar.gz (58.9 MB view details)

Uploaded Source

Built Distribution

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

zipfinder-2.0.0-py3-none-any.whl (58.9 MB view details)

Uploaded Python 3

File details

Details for the file zipfinder-2.0.0.tar.gz.

File metadata

  • Download URL: zipfinder-2.0.0.tar.gz
  • Upload date:
  • Size: 58.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.5

File hashes

Hashes for zipfinder-2.0.0.tar.gz
Algorithm Hash digest
SHA256 d036738030872a5e2d0a918fd8f4c7d95b384d53953b3e291d500987c94ce1d9
MD5 ae72adbd916406af48dafe76f52be8a7
BLAKE2b-256 224c58e6debf90b499367aab268f9d28feecf18faf3b3cae89244049a25e05d0

See more details on using hashes here.

File details

Details for the file zipfinder-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: zipfinder-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 58.9 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.5

File hashes

Hashes for zipfinder-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 25ff13dbc1df4a1f88e4d8e201dfc365d5a2e4fab464d5796b320d517d14e185
MD5 354d18a6eda152377d9a8c3d5d08e461
BLAKE2b-256 a2b367df22bf2dd2fdf7012092b18dea4c68b4b3c02daf183c49817be2cd42c0

See more details on using hashes here.

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