Skip to main content

High-level bindings to the Valhalla C++ library

Project description

Valhalla Python bindings

pyvalhalla version

This folder (src/bindings/python) contains the Python bindings for the Valhalla routing engine.

[!NOTE] pyvalhalla packages are currently only published for:

  • linux-x86_x64
  • linux-aarch64
  • win-amd64
  • macos-arm64

On top of the (very) high-level Python bindings, we package some data-building Valhalla executables to ease the process of graph creation or run Valhalla as a service, see below.

Installation

We publish CPython packages as binary wheels for Win (amd64), MacOS (arm64) and Linux (x86_64/aarch64) distributions with glibc>=2.28. To decrease disk footprint of the PyPI releases, we only publish a single abi3 wheel per platform, which requires Python >= 3.12. To install on Python < 3.12, make sure to install the system dependencies as described in the docs before trying a pip install pyvalhalla.

Or manually in the current Python environment with e.g.

git clone https://github.com/valhalla/valhalla
cd valhalla
pip install .

In case you need to do a source installation (from sdist), follow the build instructions for your platform to install the needed dependencies. Then a simple pip install pyvalhalla should work fine for Linux/OSX. On Windows one needs to install C++ developer tools, see also below in the developer notes for external vcpkg usage to resolve dependencies.

[!TIP] For developers: pip install -e (editable build) will by default build into a temp directory, so everytime it's invoked it'll rebuild all of libvalhalla. Use the following command to enable real incremental builds:

pip install -e . --no-build-isolation \
  -Cbuild-dir=build_python (or other build dir) \
  -Ccmake.build-type=Release \
  -Ccmake.define.VALHALLA_VERSION_MODIFIER="$(git rev-parse --short HEAD)"
  # optionally for vcpkg package management
  -Ccmake.define.CMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"
  -Ccmake.define.VCPKG_TARGET_TRIPLET=x64-windows
  -Ccmake.define.VCPKG_OVERLAY_PORTS=overlay-ports-vcpkg

Similarly for building a wheel:

pip wheel . -w dist --no-build-isolation \
  -Cbuild-dir=build_python (or other build dir) \
  -Ccmake.build-type=Release \
  -Ccmake.define.VALHALLA_VERSION_MODIFIER="$(git rev-parse --short HEAD)"
  # optionally for vcpkg package management
  -Ccmake.define.CMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"
  -Ccmake.define.VCPKG_TARGET_TRIPLET=x64-windows
  -Ccmake.define.VCPKG_OVERLAY_PORTS=overlay-ports-vcpkg

Both commands have to repeated for each build.

Typing support

We (try to) include full typing support for pyvalhalla. If you're using mypy with strict typing policies, you'll need to install pyvalhalla appropriately with pip install pyvalhalla[typing].

Usage

Bindings

Find a more extended notebook in ./examples, e.g. how to use the actor.

Before using the Python bindings you need to have access to a routable Valhalla graph. Once you installed the pyvalhalla package you can create one with

wget https://download.geofabrik.de/europe/andorra-latest.osm.pbf
python -m valhalla valhalla_build_tiles -c <valhalla.json> andorra-latest.osm.pbf

Once you have created a graph locally, you can use it like this:

from valhalla import Actor, get_config, get_help

# generate configuration
config = get_config(tile_extract='./custom_files/valhalla_tiles.tar', verbose=True)

# print the help for specific config items (has the same structure as the output of get_config()
print(get_help()["service_limits"]["auto"]["max_distance"])

# instantiate Actor to load graph and call actions
actor = Actor(config)
route = actor.route({"locations": [...]})

Error Handling

When a routing operation fails, a ValhallaError is raised (a subclass of RuntimeError) with structured fields from Valhalla's internal error codes:

from valhalla import Actor, ValhallaError, get_config

actor = Actor(get_config(tile_extract='./valhalla_tiles.tar'))

try:
    actor.route({"locations": [{"lat": 0.0, "lon": 0.0}, {"lat": 0.1, "lon": 0.1}], "costing": "auto"})
except ValhallaError as e:
    print(e.code)          # 171
    print(e.message)       # "No suitable edges near location"
    print(e.http_code)     # 400
    print(e.http_message)  # "Bad Request"

Graph Utilities

Access to low-level graph data structures for advanced use cases:

from valhalla.utils.graph_utils import GraphId, GraphUtils

# Create a GraphId from its string representation or numeric value
edge_id = GraphId("2/421920/20")  # format: "level/tileid/id"
# or
edge_id = GraphId(674464020)

# Initialize GraphUtils with config (reuse for multiple queries)
# Accepts: file path (str/Path), JSON string, or dict
config = "/path/to/valhalla.json"
# or dict config
config = {"mjolnir": {"tile_extract": "/path/to/tiles.tar"}}
graph = GraphUtils(config)

# Get the polyline geometry for an edge
shape = graph.get_edge_shape(edge_id)

# shape is a list of (lon, lat) tuples
print(f"Edge has {len(shape)} coordinate points")
for lon, lat in shape:
    print(f"  ({lon:.6f}, {lat:.6f})")

# Convert to GeoJSON LineString
geojson = {
    "type": "Feature",
    "geometry": {
        "type": "LineString",
        "coordinates": [[lon, lat] for lon, lat in shape]
    }
}

Speed Compression Utilities

Valhalla uses DCT-2 (Discrete Cosine Transform) to compress historical speed profiles. These utilities allow you to work with compressed speed data:

import numpy as np
from valhalla.utils.predicted_speeds import (
    compress_speed_buckets,
    decompress_speed_bucket,
    encode_compressed_speeds,
    decode_compressed_speeds,
    BUCKETS_PER_WEEK,
    COEFFICIENT_COUNT,
)

# Compress 2016 speed buckets (7 days × 288 five-minute intervals)
speeds = np.full(BUCKETS_PER_WEEK, 50.0, dtype=np.float32)  # 50 KPH constant
coefficients = compress_speed_buckets(speeds)

# Decompress a specific bucket (e.g., Monday 10:00 AM)
bucket_idx = 120  # (24 hours × 12 buckets/hour) × 0 days + 10 × 12
speed = decompress_speed_bucket(coefficients, bucket_idx)

# Encode coefficients for storage/transmission
encoded = encode_compressed_speeds(coefficients)
print(f"Compressed to {len(encoded)} characters")

# Decode from string
coefficients_restored = decode_compressed_speeds(encoded)

Valhalla executables

C++ executables

To access the C++ (native) executables, there are 2 options:

  • (recommended) execute the module, e.g. python -m valhalla valhalla_build_tiles -h
  • execute the Python wrapper scripts directly, e.g. valhalla_build_tiles -h

[!NOTE] For the latter option to work, the Python environment's bin/ folder has to be in the $PATH. Inside virtual environments, that's always the case.

Executing the scripts directly might also not work properly if there's a system-wide Valhalla installation, unless the Python environment's bin/ folder has higher priority than system folders in $PATH. The module execution uses an explicit Python executable which should be preferred.

There are also some additional commands we added:

  • --help: print the help for python -m valhalla explicitly
  • --quiet: redirect stdout of the C++ executables to /dev/null; can be added once anywhere in the command, will not be forwarded to a C++ executable
  • print_bin_path: simply prints the absolute path to the package-internal bin/ directory where the C++ executables are; useful if the executables should be accessed directly in some script

To find out which Valhalla executables are currently included, run python -m valhalla --help. We limit the number of executables to control the wheel size. However, we're open to include any other executable if there's a good reason.

Pure Python scripts

The following tools are implemented in pure Python and installed as console scripts:

  • valhalla_build_config: Generate or merge Valhalla configuration JSON files
  • valhalla_build_elevation: Download elevation (DEM) tiles for a given region
  • valhalla_build_extract: Create tar extracts from routing tiles

These are invoked directly, e.g. valhalla_build_config -h or valhalla_build_extract -h. They do not go through the python -m valhalla module mechanism.

Building from source

Note, building the bindings from source is usually best done by building Valhalla with cmake -B build -DENABLE_PYTHON_BINDING=ON .... However, if you want to package your own pyvalhalla bindings for some reason (e.g. fork in a bigger team), you can follow the below instructions, which are also executed by our CI.

The Python build respects a few CMake configuration variables:

  • VALHALLA_VERSION_MODIFIER (optional): Will append a string to the actual Valhalla version string, e.g. $(git rev-parse --short HEAD) will append the current branch's commit hash.

cibuildwheel

On our CI, this orchestrates the packaging of all pyvalhalla wheels for every supported, minor Python version and every platform. It can also be run locally (obviously only being able to build wheels for your platform), e.g.

python -m pip install cibuildwheel
cibuildwheel --print-build-identifiers
cibuildwheel --only cp313-manylinux_x86_64

# for windows you'll have to set an env var to the vcpkg win root
VCPKG_ARCH_ROOT="build/vcpkg_installed/custom-x64-windows" cibuildwheel --only cp313-win_amd64

The build looks at a few environment variables:

  • VCPKG_ARCH_ROOT (required for Win): The relative/absolute directory of the vcpkg root.

In the end, you'll find the wheel in ./wheelhouse.

Linux

To package arch-dependent Linux bindings we use a manylinux fork, where we install all dependencies into the manylinux_2_28 image, based on AlmaLinux 8. This is necessary to have a broad glibc compatibility with many semi-recent Linux distros.

Either pull the manylinux image, or build it locally for testing:

docker pull ghcr.io/valhalla/manylinux:2_28_valhalla_python

# or pull the image from ghcr.io
git clone https://github.com/valhalla/manylinux
cd manylinux
POLICY=manylinux_2_28 PLATFORM=x86_64 COMMIT_SHA=$(git rev-parse --verify HEAD) BUILDX_BUILDER=builder-docker-container ./build.sh
docker tag quay.io/pypa/manylinux_2_28_x86_64:$(git rev-parse --verify HEAD) ghcr.io/valhalla/manylinux:2_28_valhalla_python

Once built, start a container to actually build Valhalla using AlmaLinux 8:

cd valhalla
docker run -dt -v $PWD:/valhalla-py --name valhalla-py --workdir /valhalla-py ghcr.io/valhalla/manylinux:2_28_valhalla_python
docker exec -t valhalla-py /valhalla-py/src/bindings/python/scripts/build_manylinux.sh build_manylinux 3.13

This will also build & install libvalhalla before building the bindings. At this point there should be a wheelhouse folder with the fixed python wheel, ready to be installed or distributed to arbitrary python 3.13 installations.

Testing (linux only)

We have a small test script which makes sure that all the executables are working properly. If run locally for some reason, install a pyvalhalla wheel first. We run this in CI in a fresh Docker container with no dependencies installed, mostly to verify dynamic linking of the vendored dependencies.

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

pyvalhalla-3.7.0.tar.gz (35.8 MB view details)

Uploaded Source

Built Distributions

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

pyvalhalla-3.7.0-cp312-abi3-win_amd64.whl (24.3 MB view details)

Uploaded CPython 3.12+Windows x86-64

pyvalhalla-3.7.0-cp312-abi3-manylinux_2_28_x86_64.whl (35.3 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ x86-64

pyvalhalla-3.7.0-cp312-abi3-manylinux_2_28_aarch64.whl (32.8 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ ARM64

pyvalhalla-3.7.0-cp312-abi3-macosx_14_0_arm64.whl (23.8 MB view details)

Uploaded CPython 3.12+macOS 14.0+ ARM64

File details

Details for the file pyvalhalla-3.7.0.tar.gz.

File metadata

  • Download URL: pyvalhalla-3.7.0.tar.gz
  • Upload date:
  • Size: 35.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyvalhalla-3.7.0.tar.gz
Algorithm Hash digest
SHA256 46c6d2ea0961573e2535c8d13617f267f34dc1d4848a5d9e576881a056f9068f
MD5 ced1a15717cf27d466294b061fdc258b
BLAKE2b-256 3e988b51e57ed6f6258298f45b4dc6ddca533180aebe853649429edfb941b3f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvalhalla-3.7.0.tar.gz:

Publisher: osx_win_python_builds.yml on valhalla/valhalla

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

File details

Details for the file pyvalhalla-3.7.0-cp312-abi3-win_amd64.whl.

File metadata

  • Download URL: pyvalhalla-3.7.0-cp312-abi3-win_amd64.whl
  • Upload date:
  • Size: 24.3 MB
  • Tags: CPython 3.12+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyvalhalla-3.7.0-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 edfc7ae3dbff0ba2de7f555a8c6e2e1e736d2cd08ff1c5781026622f2ad7b4ef
MD5 da967948e1fd01c7cf0a95954b141dc2
BLAKE2b-256 49bd509b71c3e0bf20d9a98d41c75a30771cc3c6242cfdc574e68edb1258682a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvalhalla-3.7.0-cp312-abi3-win_amd64.whl:

Publisher: osx_win_python_builds.yml on valhalla/valhalla

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

File details

Details for the file pyvalhalla-3.7.0-cp312-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pyvalhalla-3.7.0-cp312-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 34a74b35d82cfb7a18ecbd277d152cb2423602c67b6d94d8ce56f5d326a2836a
MD5 282d59f8e44454cffa392db6028b3f1f
BLAKE2b-256 5ea9ba084343cd33b1c5edc8349811499000e781f88828665c09b1f953bef3f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvalhalla-3.7.0-cp312-abi3-manylinux_2_28_x86_64.whl:

Publisher: osx_win_python_builds.yml on valhalla/valhalla

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

File details

Details for the file pyvalhalla-3.7.0-cp312-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pyvalhalla-3.7.0-cp312-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 b0e9c766d9e860e3d2c0bc7013785b8bb0ef514351964bc45f50401faf267a61
MD5 d24e2fff005abe0f05db29891178e755
BLAKE2b-256 82244d79420fd84412b67ded1ef68dc47d0104993e410cde94e46483432d19e6

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvalhalla-3.7.0-cp312-abi3-manylinux_2_28_aarch64.whl:

Publisher: osx_win_python_builds.yml on valhalla/valhalla

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

File details

Details for the file pyvalhalla-3.7.0-cp312-abi3-macosx_14_0_arm64.whl.

File metadata

File hashes

Hashes for pyvalhalla-3.7.0-cp312-abi3-macosx_14_0_arm64.whl
Algorithm Hash digest
SHA256 08eeb10e013da1a0ffdec76e42346495fce8d612790a656a46b64f96becbad17
MD5 6e00f50498c22d0daf8d084f02512dee
BLAKE2b-256 0b66bcfd21404a8027eb21167566d5c07ab32e2a8e14f5ebf6d0b4162139c3ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyvalhalla-3.7.0-cp312-abi3-macosx_14_0_arm64.whl:

Publisher: osx_win_python_builds.yml on valhalla/valhalla

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