Client Python
Le client cartiflette publié sur PyPI lit en HTTPS les fichiers que le pipeline a écrits dans projet-cartiflette/production. Tout le traitement se fait avec DuckDB ; le résultat est converti en geopandas.GeoDataFrame à la fin (par défaut), ou rendu tel quel sous forme de relation DuckDB. Son code est dans python-package/cartiflette/, avec son propre pyproject.toml, son uv.lock et ses tests. Il n’importe rien du pipeline. Il demande Python 3.10 ou plus et DuckDB 1.5 ou plus.
La liste complète des fonctions est dans la référence de l’API, générée depuis les docstrings par quartodoc.
Utilisation
pip install cartiflettefrom cartiflette import carti_download
# Départements, DROM rapprochés de la métropole (GeoDataFrame)
france = carti_download(
values=["France"],
borders="DEPARTEMENT",
filter_by="FRANCE_ENTIERE_DROM_RAPPROCHES",
simplification=50,
year=2025,
)
# Communes de deux régions, gardées dans DuckDB pour continuer en SQL
communes = carti_download(
values=["11", "84"],
borders="COMMUNE",
filter_by="REGION",
year=2025,
engine="duckdb",
)
communes.aggregate("INSEE_REG, sum(POPULATION)")Moteur : engine
"geopandas"(défaut) : renvoie unGeoDataFrame. La lecture et le filtrage sont faits par DuckDB, la conversion n’a lieu qu’à la fin (to_geopandas)."duckdb": renvoie la relation DuckDB, pas encore évaluée, avec une colonnegeometryde typeGEOMETRY. Le paramètreconpermet d’utiliser sa propre connexion (par exemple pour joindre le résultat à d’autres tables) ; par défaut, une connexion en mémoire est partagée par tous les appels.
Filtrer les polygones : where
where garde, parmi les polygones de values, ceux qui vérifient une expression SQL DuckDB, comme dans une clause WHERE (filter_relation). Elle peut porter sur les attributs (POPULATION, NOM, INSEE_DEP, les codes de zonage…) et sur la colonne geometry, avec les fonctions de l’extension spatial de DuckDB. Le filtre est appliqué avant la conversion, quels que soient le format et engine. Sur le GeoParquet, DuckDB l’applique pendant la lecture : il ne télécharge que les groupes de lignes qui peuvent contenir des polygones retenus, grâce aux statistiques (emprise des géométries comprise) écrites dans le fichier.
values et filter_by restent obligatoires : pour chercher dans toute la France, values="France" et filter_by="FRANCE_ENTIERE". Les coordonnées s’écrivent en (longitude, latitude), dans le système de crs (WGS84 par défaut).
Filtre attributaire : les communes de plus de 2 000 habitants d’Occitanie (542 communes sur 4 446 en 2026).
villes = carti_download(
values="76",
borders="COMMUNE",
filter_by="REGION",
year=2026,
where="POPULATION > 2000",
)Toute expression SQL est possible : "INSEE_DEP IN ('31', '32') AND POPULATION > 2000", "STATUT = 'Préfecture'", "NOM ILIKE 'saint%'"…
Emprise (bounding box) : les communes qui touchent un rectangle, ici la Camargue, à cheval sur deux régions (Gard et Hérault en Occitanie, Bouches-du-Rhône en Provence-Alpes-Côte d’Azur). C’est le fond de carte d’une carte centrée sur une zone qui ne correspond à aucun découpage administratif, ou de l’emprise affichée par une carte web.
camargue = carti_download(
values="France",
borders="COMMUNE",
filter_by="FRANCE_ENTIERE",
year=2026,
# ST_MakeEnvelope(longitude min, latitude min, longitude max, latitude max)
where="ST_Intersects(geometry, ST_MakeEnvelope(4.1, 43.3, 4.9, 43.75))",
)Distance à un point : les communes situées à moins de 20 km de la centrale nucléaire du Bugey (Ain), le rayon des plans particuliers d’intervention. Les distances se calculent en mètres dans une projection adaptée : Lambert 93 (EPSG:2154) pour la métropole.
autour_du_bugey = carti_download(
values="France",
borders="COMMUNE",
filter_by="FRANCE_ENTIERE",
year=2026,
where="""
ST_DWithin(
ST_Transform(geometry, 'EPSG:4326', 'EPSG:2154'),
ST_Transform(ST_Point(5.2706, 45.7983), 'EPSG:4326', 'EPSG:2154'),
20000
)
""",
)Cette expression garde les communes dont une partie est à moins de 20 km (121 communes de l’Ain, de l’Isère et du Rhône). Pour le centre de la commune plutôt que son contour, et partout (DROM compris, sans changer de projection), la distance sur la sphère : "ST_Distance_Sphere(ST_Centroid(geometry), ST_Point(1.4442, 43.6047)) < 30000" (communes dont le centre est à moins de 30 km du Capitole de Toulouse).
Point dans un polygone : la commune ou l’arrondissement qui contient un point, par exemple pour rattacher une adresse géocodée.
carti_download(
values="75",
borders="COMMUNE_ARRONDISSEMENT",
filter_by="DEPARTEMENT",
year=2026,
where="ST_Contains(geometry, ST_Point(2.2945, 48.8584))", # Tour Eiffel
) # Paris 7e arrondissementLes filtres se combinent : "POPULATION > 2000 AND ST_Intersects(geometry, ...)". Une expression invalide (syntaxe, colonne ou fonction inconnue) lève une ValueError. Mesures depuis le SSPCloud, millésime 2026, simplification 50 : 0,1 à 0,4 s pour chacun de ces exemples, y compris sur la France entière.
La connexion du client active geometry_always_xy : ST_Transform depuis EPSG:4326 et ST_Distance_Sphere lisent les coordonnées en (longitude, latitude), l’ordre des fichiers. Sans ce réglage, DuckDB les lit en (latitude, longitude) et les distances sont fausses (440 km entre Paris et Lyon au lieu de 391 km). Avec une connexion passée par con, le client l’active aussi.
Format : vectorfile_format
Les deux formats ne s’utilisent pas de la même façon :
- GeoJSON : un fichier par valeur de
filter_by, publié seulement pour les millésimes antérieurs à la refonte (2022) : le pipeline n’en produit plus, le GeoJSON des nouveaux millésimes est servi par l’API (04). Le client construit la liste des liens (geojson_urls, aveccreate_path_bucket) et DuckDB les lit ensemble (read_geojson,read_json). - GeoParquet : un seul fichier par niveau (
create_path_consolidated), qui contient toute la France. Le client lit la métadonnéecartiflette:filter_columnspour savoir quelle colonne correspond àfilter_by, puis ajoute unWHERE(read_parquet). DuckDB ne télécharge que les groupes de lignes utiles, grâce au tri du fichier, à ses statistiques et à ses filtres de Bloom : sur le fichier des communes 2025 (35 Mo), un département, un bassin de vie ou une zone d’emploi coûtent environ 2 Mo, une région 2 à 7 Mo. Une erreur est levée si une valeur n’existe pas ou si le niveau ne peut pas être filtré ainsi (ex. des régions par département).
Le GeoParquet est lu dès qu’il existe (à partir de 2025, et pour les années antérieures où il a été produit : parquet_available le vérifie par une requête HEAD, puis choose_format décide), même si vectorfile_format="geojson" est demandé : un avertissement l’indique. Il est aussi rapide que le GeoJSON pour une petite requête et bien plus rapide pour une grosse. Pour lire quand même le GeoJSON, passer force=True (un avertissement rappelle que le GeoParquet est plus rapide) : seulement pour les millésimes qui ont des fichiers GeoJSON (2022). À partir de 2025, ou pour un millésime republié par le pipeline actuel, il n’y en a pas (geojson_available le vérifie) : le GeoParquet est lu malgré force=True, avec un avertissement. Sans GeoParquet (ex. 2022 en production aujourd’hui), le GeoJSON est lu sans avertissement. Mesures depuis le SSPCloud, millésime 2025, simplification 50 :
| Requête | GeoParquet | GeoJSON |
|---|---|---|
| Communes d’un département | 0,2–0,3 s | 0,1 s |
| Communes d’une région (84) | 0,5 s | 1,1 s |
| Départements, DROM rapprochés | 0,4 s | 0,8 s |
| Toutes les communes | 2,2 s | 16 s |
Combinaisons disponibles
Elles correspondent à FILTERS dans cartiflette/pipeline.py. Chaque combinaison existe avec simplification 0, 50 et 80 (part des points retirés, 80 par défaut), en crs=4326. Les GeoJSON de 2022 n’existent qu’en 0 et 50 : le défaut y est 50.
borders (polygones) |
filter_by (découpage) |
|---|---|
COMMUNE, COMMUNE_ARRONDISSEMENT |
BASSIN_VIE, ZONE_EMPLOI, UNITE_URBAINE, AIRE_ATTRACTION_VILLES, DEPARTEMENT, REGION, TERRITOIRE, FRANCE_ENTIERE, FRANCE_ENTIERE_DROM_RAPPROCHES |
IRIS (à partir de 2025) |
COMMUNE, COMMUNE_ARRONDISSEMENT, BASSIN_VIE, ZONE_EMPLOI, UNITE_URBAINE, AIRE_ATTRACTION_VILLES, DEPARTEMENT, REGION, TERRITOIRE, FRANCE_ENTIERE, FRANCE_ENTIERE_DROM_RAPPROCHES |
CARREAU_200M, CARREAU_1KM (Insee, Filosofi) |
COMMUNE, COMMUNE_ARRONDISSEMENT, DEPARTEMENT, REGION, BASSIN_VIE, ZONE_EMPLOI, UNITE_URBAINE, AIRE_ATTRACTION_VILLES, TERRITOIRE, FRANCE_ENTIERE |
DEPARTEMENT |
REGION, TERRITOIRE, FRANCE_ENTIERE, FRANCE_ENTIERE_DROM_RAPPROCHES |
REGION, BASSIN_VIE, ZONE_EMPLOI, UNITE_URBAINE, AIRE_ATTRACTION_VILLES |
TERRITOIRE, FRANCE_ENTIERE, FRANCE_ENTIERE_DROM_RAPPROCHES |
Valeurs de values selon le découpage : un code Insee ("75", "11"), le nom d’un territoire ("metropole", "guadeloupe"…) ou "France".
Les carreaux de l’Insee (CARREAU_200M, CARREAU_1KM, dispositif Filosofi) sont des carrés : ils n’existent qu’avec simplification=0, que le client lit toujours pour eux, et ils ne sont pas proposés en FRANCE_ENTIERE_DROM_RAPPROCHES. Ils gardent les variables de l’Insee (idcar_200m, ind, men, ind_snv, i_est_200, lcog_geo…). Chaque carreau est rattaché à une seule commune, celle qui contient son centre (INSEE_COM, INSEE_COG, NOM_COM et les zonages de la commune) : les carreaux d’un département le pavent sans doublon. lcog_geo liste toutes les communes recouvertes, dans la géographie des données, pour un filtre where.
Formats et millésimes
- À partir de 2025 :
parquetseulement (alias accepté :geoparquet) ; le client lit leparquetmême sigeojsonest demandé,force=Truecompris. Le GeoJSON de ces millésimes est servi par l’API (04). - Avant 2025 :
geojsonseulement en production pour 2022 (ancien pipeline) ; le client bascule seul sur leparquetsi celui-ci est publié (2022 à 2024 peuvent être produits depuis les éditions IGN 3-x). - Codes de région :
1,"1"et"01"sont acceptés. Le client essaieREGION=01(fichiers depuis 2025) puisREGION=1(fichiers plus anciens), voirvalue_candidates.
Extensions DuckDB et proxy
Au premier appel, DuckDB télécharge ses extensions httpfs et spatial (depuis extensions.duckdb.org) et les garde dans ~/.duckdb. Derrière un proxy, définir la variable d’environnement https_proxy, transmise à DuckDB. Il n’y a plus de cache persistant des fichiers téléchargés : le GeoParquet ne rapatrie que ce qui est demandé.
Lire une sortie de test
Les paramètres bucket et path_within_bucket permettent de lire un autre emplacement que la production. C’est utile pour relire une exécution du pipeline écrite dans l’espace de test (voir Vérifier et faire évoluer) :
carti_download(values="11", borders="DEPARTEMENT", filter_by="REGION",
year=2026, path_within_bucket="test/v0.3.0")Développer le client
cd python-package/cartiflette
uv run pytest tests # tests `network` : lecture seule en production
uv run pytest tests -m "not network" # hors lignecreate_path_consolidateddoit rester identique àcartiflette/paths.pydans le pipeline (voir Les parties du projet). Les deux suites de tests fixent la même chaîne attendue.create_path_bucketn’existe plus que dans le client, pour lire les GeoJSON déjà publiés : ne pas le modifier.- Docstrings au format numpydoc : elles alimentent la référence de l’API.
- Publication : monter
versiondanspython-package/cartiflette/pyproject.toml, puis pousser un tagv*. Le workflowpypi.ymlconstruit et publie le paquet (voir Versions, images et publication).
Construire cette documentation
La référence de l’API est générée par quartodoc, installé dans le groupe de dépendances docs du client. Il faut la régénérer avant de construire le site :
cd doc
uv run --project ../python-package/cartiflette --group docs quartodoc build
quarto render # ou quarto previewLes pages générées (doc/reference/, doc/objects.json) ne sont pas versionnées.
Publication
Le workflow .github/workflows/docs.yml publie sur GitHub Pages (https://inseefrlab.github.io/cartiflette/) un site unique :
- à la racine, le site cartiflette-website (exemples, cas d’usage), dont les exemples Python sont exécutés avec le client de ce dépôt ;
- sous
doc/, ce site-ci.
Le lien « Documentation Python » de la barre de navigation du site principal est ajouté par un profil Quarto, doc/website/_quarto-cartiflette.yml, copié dans le dépôt cartiflette-website au moment du rendu. Le workflow tourne à chaque modification de doc/ ou du client sur main, à la main (workflow_dispatch), ou quand cartiflette-website envoie un événement repository_dispatch de type cartiflette-website. Sur une pull request, il vérifie seulement la construction.