Skip to main content

Offline country profiles, coordinate tools, and geography learning utilities

Project description

PyWorldAtlas

A compact, source-aware world atlas for Python that works completely offline.

Source 0.3.0 PyPI Python 3.10–3.14 Runtime dependencies: 0 Offline: yes License: MIT

PyWorldAtlas makes real geographic data feel like ordinary Python. Look up a country by name or code, inspect immutable country and capital objects, explore major cities, calculate geographic relationships, and build reproducible learning material—without an API key, runtime download, database server, or third-party dependency.

from pyworldatlas import Atlas

with Atlas() as atlas:
    japan = atlas.country("Japan")

    print(japan.capital.name)                  # Tokyo
    print(japan.capital.coordinates.as_tuple())
    print(atlas["DO"].name)                    # Dominican Republic
    print("France" in atlas)                   # True

Dataset coverage

The bundled dataset contains every country and area in the captured UN M49 scope, cross-checked against GeoNames country metadata. Version 0.3.0 adds a reviewed land-border graph to the profile, coordinate, capital, and populated-place records established in earlier releases.

Current dataset Coverage
Countries and areas 248
Primary capitals 241 / 248
Capital coordinates 241 / 241
Populated-place records 6,265, including retained capitals
Reviewed land borders 319 undirected relationships
Countries and areas without an accepted land border 85
Runtime dependencies 0
Bundled databases 1 SQLite file

The 0.3.0 checkout includes richer country profiles, dependency-free coordinate calculations, flag emoji, discovery cards, reproducible sampling, structured flashcards, reviewed neighbors, and shortest land-border paths. Boundary geometry, historical statistics, national leaders, interactive learning applications, and exports remain later work.

Installation

Install the latest published release:

python -m pip install --upgrade pyworldatlas

Install the current source checkout and its separate data builder when contributing:

python -m pip install -e . -e pipeline

You can also test the exact local wheel after running the release build:

python -m pip install --no-index --no-deps dist/pyworldatlas-0.3.0-py3-none-any.whl

The package runtime supports Python 3.10 through 3.14 during the 0.x release series. Python versions are only claimed as release-supported after CI passes.

What works in this checkout

Capability Example
Exact lookup atlas.country("Japan")
Standard identifiers atlas.country("JP"), atlas.country("JPN"), atlas.country("392")
Familiar aliases atlas.country("USA"), atlas.country("Holy See")
Collection behavior atlas["DO"], "France" in atlas, len(atlas)
Ranked search atlas.search_countries("united")
Geographic filtering atlas.countries(continent="Americas")
Capital records country.capital, .coordinates, .timezone_id
Major cities atlas.major_cities("Japan", limit=5)
Rich profile country.population, .currency, .languages, .calling_codes
Flags and calculated facts country.flag_emoji, .population_density
Discovery cards country.discovery_card()
Stable country samples atlas.sample_countries(count=5, seed=42)
Structured flashcards atlas.flashcards(topic="capitals", count=10, seed=42)
City coordinates atlas.coordinates("Tokyo", country="JP")
Distance atlas.distance_between("Tokyo", "Paris", first_country="JP", second_country="FR")
Bearing and midpoint coordinate.bearing_to(other), .midpoint_to(other)
Land neighbors atlas.neighbors("France"), atlas.shares_border("ES", "MA")
Border paths atlas.border_path("Portugal", "China"), atlas.border_crossings(...)
Land components atlas.countries_reachable_by_land("Portugal")
Borderless entities atlas.countries_with_no_land_borders()
Source inspection country.sources
Official local names country.local_names, country.name_in("pt")
Serialization country.to_dict(), country.to_json()
Version inspection atlas.dataset_info()

Typed country profiles

Public results are frozen typed dataclasses rather than loosely structured dictionaries:

from pyworldatlas import Atlas

with Atlas() as atlas:
    country = atlas.country("Dominican Republic")

    print(country.name)
    print(country.official_name)
    print(country.flag)
    print(country.flag_emoji)
    print(country.codes.alpha2)
    print(country.codes.alpha3)
    print(country.codes.numeric)
    print(country.continent)
    print(country.region)
    print(country.subregion)
    print(country.area_km2)
    print(country.population)
    print(country.population_density)
    print(country.currency)
    print(country.languages)
    print(country.calling_codes)
    print(country.top_level_domain)
    print(country.observed_timezones)

    if country.capital is not None:
        print(country.capital.name)
        print(country.capital.coordinates.as_tuple())
        print(country.capital.population)
        print(country.capital.timezone_id)

Country discovery and education

from pyworldatlas import Atlas

with Atlas() as atlas:
    japan = atlas.country("Japan")
    card = japan.discovery_card()

    print(card.flag_emoji, card.capital, card.population_density)

    for country in atlas.sample_countries(count=5, continent="Africa", seed=42):
        print(country.flag_emoji, country.name)

    for flashcard in atlas.flashcards(topic="capitals", count=3, seed=42):
        print(flashcard.prompt)
        print(flashcard.answer)

Sampling uses a versioned SHA-256 ranking over stable M49 identifiers, so the same dataset, filters, and seed produce the same ordered lesson across supported Python versions. Flashcards are immutable structured values rather than an interactive game. Supported topics cover capitals, flags, country codes, currencies, calling codes, domains, language codes, regions, local names, population, area, and calculated density.

Latitude, longitude, and distance

from pyworldatlas import Atlas, Coordinate

with Atlas() as atlas:
    tokyo = atlas.city("Tokyo", country="Japan")
    paris = atlas.city("Paris", country="France")

    print(tokyo.coordinates.latitude, tokyo.coordinates.longitude)
    print(atlas.distance_between(tokyo, paris))             # kilometres
    print(atlas.distance_between(tokyo, paris, unit="mi"))  # miles
    print(tokyo.coordinates.bearing_to(paris.coordinates))
    print(tokyo.coordinates.midpoint_to(paris.coordinates))

london = Coordinate(51.5074, -0.1278)
paris_center = Coordinate(48.8566, 2.3522)
print(london.distance_to(paris_center))

Distances use the haversine formula and WGS84 mean Earth radius. They are surface great-circle distances, not road or flight-routing distances.

Search and filter

with Atlas() as atlas:
    for match in atlas.search_countries("united"):
        print(match.country.name, match.matched_name, match.score)

    for country in atlas.countries(continent="Europe"):
        capital = country.capital.name if country.capital else "not available"
        print(country.name, capital)

Search is case- and accent-insensitive. Exact country lookup accepts common names, reviewed aliases, alpha-2, alpha-3, and M49 numeric codes.

Land borders and shortest paths

The 0.3.0 graph contains 319 reviewed undirected relationships. Neighbor results are alphabetical, and equal-length shortest paths are deterministic.

from pyworldatlas import Atlas

with Atlas() as atlas:
    print([country.name for country in atlas.neighbors("France")])
    print(atlas.shares_border("Spain", "Morocco"))

    path = atlas.border_path("Portugal", "China")
    print(path.crossings)
    print(" -> ".join(country.name for country in path.countries))

    print(atlas.border_path("Japan", "China"))  # None

border_path() uses breadth-first search and returns an immutable, JSON-serializable BorderPathResult. A missing route is None, not an error. Maritime proximity, border geometry, border length, and road routing are not represented.

Small by design

The installed wheel contains only:

  • Python source files.
  • One generated, read-only SQLite database.
  • Standard package metadata.

At runtime PyWorldAtlas does not:

  • Contact the internet.
  • Require an API key.
  • Download or decompress data after installation.
  • Write into site-packages.
  • Load the complete database during Atlas() initialization.
  • Depend on pandas, NumPy, an ORM, a GIS engine, or SQLite extensions.

Data you can trace

The 0.3.0 checkout uses:

  • United Nations M49 for canonical identities, standard codes, regions, and subregions.
  • GeoNames for capitals, populated places, WGS84 coordinates, population snapshots, currencies, language and calling codes, country-code domains, timezone identifiers, GeoNames IDs, and one input to border review.
  • Natural Earth public-domain 1:50m map units as an independent land-border topology check.

The reviewed local-name records use the UNGEGN List of Country Names (E/CONF.105/13/CRP.13) for national official short and formal names. Current coverage is five records across Brazil and Switzerland. The captured source artifact and reviewed rows include checksums and exact entry/page locators.

Raw snapshots are preserved with SHA-256 manifests. The separate builder emits inspectable normalized JSON Lines before generating SQLite. Missing values stay missing; unsourced assumptions are never substituted for country facts.

Flag emoji are derived from alpha-2 codes, population density is a transparent ratio of sourced values, and discovery/learning tools only rearrange existing profile data. They introduce no additional country claims or third-party data.

The two border inputs agree on 315 relationships. Six differences have explicit decisions in build_data/reviewed/border_decisions.csv: four relationships are included and two are excluded. Any unreviewed source difference fails the data build.

Seven areas have no usable primary-capital record in the current snapshot. Their country.capital value is None. GeoNames-only country rows that do not have a matching identity in the captured UN M49 scope are excluded rather than inferred.

See DATA_SOURCES.md, DATA_QUALITY.md, and THIRD_PARTY_NOTICES.md.

Three different versions

with Atlas() as atlas:
    print(atlas.dataset_info())
  • Library version describes Python behavior and the public API.
  • Schema version describes compatibility with the bundled SQLite structure.
  • Dataset version identifies the captured source snapshot.

For this development checkout they are 0.3.0, 3, and 2026.07.21.1.

Documentation and roadmap

Version 0.3.0 is the reviewed land-border release. Later releases extend boundary geometry, historical statistics, institutions, culture, and exports.

License and attribution

PyWorldAtlas code is available under the MIT License. GeoNames data is provided under CC BY 4.0, and Natural Earth data is public domain. Other source terms and notices are recorded in THIRD_PARTY_NOTICES.md.

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

pyworldatlas-0.3.0.tar.gz (393.3 kB view details)

Uploaded Source

Built Distribution

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

pyworldatlas-0.3.0-py3-none-any.whl (387.0 kB view details)

Uploaded Python 3

File details

Details for the file pyworldatlas-0.3.0.tar.gz.

File metadata

  • Download URL: pyworldatlas-0.3.0.tar.gz
  • Upload date:
  • Size: 393.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for pyworldatlas-0.3.0.tar.gz
Algorithm Hash digest
SHA256 ee0fe897e9f43af7ea963f7ae921d0adb906ffeab66afad6780759917b045ca6
MD5 f8d1aea6debcc05ca45fbcab5eb551c0
BLAKE2b-256 50646863c93374e9bf4833ba123cf1d901409b500b42187122f2bcf329f9aaab

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyworldatlas-0.3.0.tar.gz:

Publisher: release.yml on jcari-dev/pyworldatlas

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyworldatlas-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: pyworldatlas-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 387.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for pyworldatlas-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fa93204a6197c05e2bde5e0d4867d6357d74cee1bb58154f664decc5faffd0b3
MD5 390c3a29d231f60247564825275f883b
BLAKE2b-256 41e3f28510b25cec158640354def948d1cbff539d307cbd65cbe355c783c38d8

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyworldatlas-0.3.0-py3-none-any.whl:

Publisher: release.yml on jcari-dev/pyworldatlas

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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