geopackage-toolkit
Python toolkit for GeoPackage spatial data. Validate, query, and operate on spatial data without PostGIS or ArcGIS.
Zero compiled dependencies. Uses SpatiaLite (embedded in SQLite) for all spatial operations. One file format (.gpkg), one dependency chain, clean Python API.
from geopkgtoolkit import connect, validate_layers, count_in_zones
# Validate geometry health
report = validate_layers("data.gpkg", expected_srid=4326)
print(report.summary())
# Count buildings per administrative zone
con = connect("data.gpkg")
counts = count_in_zones(con, "buildings", "admin3")
for zone_id, count in counts[:5]:
print(f"Zone {zone_id}: {count} buildings")
Why
GeoPackage is the OGC standard that replaces Shapefile. It's SQLite-based, supports vector + raster + tiles, and works everywhere. But the tooling around it is fractured:
ogr2ogrworks but isn't PythonicGeoPandasadds heavy compiled dependenciesSpatiaLitehas Windows quirks nobody documents- No single package covers validate-query-convert-publish
This toolkit fills that gap. Local-first, no server required.
Installation
pip install geopackage-toolkit
Prerequisites
SpatiaLite must be installed on your system:
| OS | Install |
|---|---|
| Windows | Download from gaia-gis.it and set SPATIALITE_DIR env var |
| Ubuntu/Debian | sudo apt install libspatialite-dev |
| macOS | brew install libspatialite |
| Conda | conda install -c conda-forge libspatialite |
CLI
# Validate geometry health
geopkg validate data.gpkg --srid 4326
# Count features per zone
geopkg count data.gpkg --features buildings --zones admin3
# Show layer info
geopkg info data.gpkg
# Buffer features (output saved as new layer in same GeoPackage)
geopkg buffer data.gpkg --layer buildings --distance 100 --output buffered_buildings
# Clip a layer to a boundary
geopkg clip data.gpkg --source buildings --clip district_boundary --output clipped_buildings
# Spatial intersection of two layers
geopkg intersect data.gpkg --layer-a buildings --layer-b flood_zones --output buildings_in_flood
Python API
Validate
from geopkgtoolkit import validate_layers, validate_layer
# Validate all layers
report = validate_layers("data.gpkg", expected_srid=4326)
print(report.summary())
# GeoPackage: data.gpkg
# 9 layers, 685,968 features, 0 warnings
# OSM_Buildings: 515,013 features, SRID=4326, OK
# lbn_adm3: 1,627 features, SRID=4326, OK
# ...
assert report.is_valid # True if no warnings
# Validate a single layer
con = validate_layer(con, "buildings", expected_srid=4326)
Checks: null geometries, empty geometries, invalid geometries (self-intersections), SRID mismatches, bounding box sanity.
Query
from geopkgtoolkit import connect, count_in_zones, bbox_filter
con = connect("data.gpkg")
# Count features per zone (rtree-accelerated)
counts = count_in_zones(con, "buildings", "admin3")
# Returns: [(zone_fid, count), ...]
# Bounding box filter (rtree-accelerated)
fids = bbox_filter(con, "buildings", (35.4, 33.8, 35.6, 33.9))
# Returns: [fid, ...]
# Point-in-polygon classification
from geopkgtoolkit import points_in_polygons
result = points_in_polygons(con, "pois", "districts")
# Returns: [(point_fid, polygon_fid_or_None), ...]
Spatial Operations
from geopkgtoolkit import connect, buffer, clip, intersect
con = connect("data.gpkg")
# Buffer features by a distance (CRS units)
buffered = buffer(con, "buildings", distance=100, output_table="buffered_buildings")
# Creates new layer with buffered polygons
# Clip features to a boundary
clipped = clip(con, "buildings", "district_boundary", output_table="clipped_buildings")
# Creates new layer with features clipped to polygon boundary
# Spatial intersection of two layers
result = intersect(con, "buildings", "flood_zones", output_table="buildings_in_flood")
# Creates new layer with the intersection of two layers
All operations write results back to the same GeoPackage file. Attributes from both layers are preserved in intersection.
Connect
from geopkgtoolkit import connect
con = connect("data.gpkg") # Auto-loads SpatiaLite
layers = con.execute("SELECT table_name FROM gpkg_geometry_columns").fetchall()
con.close()
How It Works
All spatial operations use SpatiaLite (embedded spatial SQL extension for SQLite) with GeoPackage's native rtree tables for spatial indexing. This means:
- No server process (unlike PostGIS)
- No compiled Python bindings (unlike GeoPandas/GDAL wheels)
- Single
.gpkgfile per dataset - Works on Windows, Linux, macOS
Performance
| Operation | Method | 500k features x 1k zones |
|---|---|---|
count_in_zones |
rtree bbox + ST_Contains | ~8 seconds |
count_in_zones (no index) |
ST_Contains only | >10 minutes |
bbox_filter |
rtree lookup | <1 second |
The toolkit auto-creates rtree indexes when missing. First run builds the index, subsequent runs use it.
Roadmap
- v0.1.0: Validate + Query modules
- v0.2.0: Spatial operations (buffer, clip, intersect) with CLI commands
- v0.3.0: Format conversion (Shapefile, GeoJSON, FlatGeobuf to/from GeoPackage)
- v0.4.0: Config-driven batch pipeline
- v0.5.0: Vector tile generation for web publishing
- v1.0.0: Full toolkit with visualization and schema extraction
Contributing
Contributions welcome. Please open an issue first to discuss what you'd like to change.
License
MIT
Acknowledgments
Built on top of SpatiaLite by Alessandro Furieri and the GeoPackage OGC standard.
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 geopackage_toolkit-0.2.0.tar.gz.
File metadata
- Download URL: geopackage_toolkit-0.2.0.tar.gz
- Upload date:
- Size: 34.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
44fdd7cf36f28277bfe2f327a1963b587d4c193c437f44465b795fd7aa40e767
|
|
| MD5 |
d357bf4dbcfc53751fe9f78f5b272669
|
|
| BLAKE2b-256 |
9af67855855bc2eb7d3a43c7b4b1c71f6245f7451b92aa4499f1f07bc32232c8
|
File details
Details for the file geopackage_toolkit-0.2.0-py3-none-any.whl.
File metadata
- Download URL: geopackage_toolkit-0.2.0-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
facd3ba1e506ec147e18e6c9abda5cd9d6ff44cce16e9028ad97300889d53471
|
|
| MD5 |
d7348d7784d4856cc203402500671d5f
|
|
| BLAKE2b-256 |
033ccc877702e3f6c0da5ca609e6f09d37921557b1d5002e91e6068c6d37d1a2
|