For rapid prototyping or for running simple test cases in Django I like to use spatialite the geospatial extension to sqlite.
To use Spatialite, you need to have SQLite compiled with extension support. However, both the built-in SQLite on macOS and the one from Homebrew lack this support. As a result, the Python version compiled by Pyenv also lacks this support, since it compiles a near-default configuration of Python, with SQLite extensions disabled by default.
Recipe
- First, uninstall sqlite if you installed it first
brew uninstall sqlite
Note that if you have package dependent from sqlite you can force the uninstall since we are re-installing sqlite.
- Reinstall sqlite from source (also install spatialite if not installed)
brew install --build-from-source sqlite
- Build python with support for sqlite extension. Here I’m building python 3.10.9 which I did not had on my machine.
PKG_CONFIG_PATH="/opt/homebrew/opt/sqlite/lib/pkgconfig" \
CPPFLAGS="-I/opt/homebrew/opt/sqlite/include" PATH="/opt/homebrew/opt/sqlite/bin:$PATH" \
LDFLAGS="-L/opt/homebrew/opt/sqlite/lib" \
PYTHON_CONFIGURE_OPTS="--enable-loadable-sqlite-extensions" \
pyenv install 3.10.9
- Create a brand new env with spatialite support
pyenv virtualenv 3.10.9 venv-with-spatialite
- Then test it in a new proj
mkdir test-spatialite && cd test-spatialite
cat venv-with-spatialite > .python-version
import sqlite3
from contextlib import closing
# Connect to a Spatialite database
with closing(sqlite3.connect(':memory:')) as conn:
with conn:
conn.enable_load_extension(True)
conn.load_extension('mod_spatialite')
# Create a table with a geometry column
with closing(conn.cursor()) as cursor:
cursor.execute('CREATE TABLE my_table (id INTEGER PRIMARY KEY, geom POINT)')
# Insert a POINT geometry
cursor.execute("INSERT INTO my_table (geom) VALUES (GeomFromText('POINT(1 1)'))")
# Convert the result set to GeoJSON
cursor.execute('SELECT id, AsGeoJSON(geom) FROM my_table')
rows = cursor.fetchall()
print(rows)