Recettes Python pour QGis: accéder aux données vecteur(shapefile)

Dans cette série d’articles nous allons voir comment accéder aux données de type vecteur avec Python et QGis. Tout d’abord nous verrons comment charger les différents formats de données vecteur (shapefile, postgis et spatialite), puis comment accéder aux propriétés géométriques et attributaires, et enfin, quelques exemples de traitement spatial de ce type de données.Parmi le grand nombre de formats possibles pour les données vecteur, nous allons voir les deux principaux: shapefile et postgis.

Pour les exemples nous allons utiliser le plugin Script Runner de QGis, mais vous pouvez taper directement les lignes de code dans la console Python de QGis.

Charger un shapefile avec Python

Nous allons utiliser un fichier shapefile disponible sur Github pour cet exemple. Vous pouvez le télécharger ici:

Nous supposons dans la suite de l’article que vous décompressez ce fichier dans un répertoire c:/data.

Démarrez QGis et ouvrez Script Runner (ceci suppose que vous l’avez déjà installé et activé).

menu de lancement du pugin script runner de qgisCliquez sur l’outil Nouveau Script

nouveau script dans scriptrunner

et nommez votre script charger_vecteur.py

Dans l’onglet Source vous aurez le contenu du fichier créé.

odèe de script créé par l'outil nouveau script de script runner de qgisOuvrez le menu contextuel du script en cliquant droit sur le nom du script et sélectionnez Edit script in external editor

editer le script avec l'éditeur externe

# Customize this starter script by adding code
# to the run_script function. See the Help for
# complete information on how to create a script
# and use Script Runner.

«  » » Your Description of the script goes here «  » »

# Some commonly used imports

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *

def run_script(iface):
layer = QgsVectorLayer(« /data/NYC_MUSEUMS_GEO.shp », « Musees de la ville de New York », « ogr »)
if not layer.isValid():
print « erreur de chargement de la couche %s  » % layer.name()
QgsMapLayerRegistry.instance().addMapLayers([layer])

Vous pouvez faire du copier-coller de ce texte, mais ATTENTION!! : vous devrez corriger l’indentation des lignes pour que le script fonctionne. L’affichage html ignore les espaces en début de ligne, mais Python…NON!

Votre script doit apparaître dans Scriptrunner comme suit:

pv6Je sais que Musées prend un accent, mais si vous voulez que le script marche il faut l’enlever. Sur la gestion des caractères accentués dans Python, cet article ne suffirait pas pour aborder ce casse-tête.

Si vous avez un message comme celui-ci:

message d'ertreur de scriptrunner lors de l'actualisation d'un script

c’est qu’il y a une erreur de syntaxe (ou un caractère accentué) dans votre script et que ScriptRunner n’arrive pas à interpréter votre code source.

Si vous exécutez le script à partir de scriptrunner vous aurez alors:

pv5

votre shapefile chargé dans QGis.

Voyons maintenant en détail ce que nous avons fait dans ce script:

layer = QgsVectorLayer(« /data/NYC_MUSEUMS_GEO.shp », « Musees de la ville de New York », « ogr »)

Cette ligne de code crée la couche (layer). QgsVectorLayer nécessite trois arguments:

  • un chemin de fichier vers les données à charger : « /data/NYC_MUSEUMS_GEO.shp« 
  • le nom que nous souhaitons donner à cette couche dans la fenêtre de QGis: « Musees de la ville de New York« 
  • et le fournisseur de données (data provider) à utiliser : ici « ogr » de la librairie GDAL. OGR détermine le format des données à partir de l’extension du fichier et adapte le driver à utiliser en fonction. Voici la liste des formats gérés par ogr:
Liste des formats vecteur OGR

Nom du Format Code Création Géoréférencement Compilé par défaut
fichiers Aeronav FAA AeronavFAA Non OUI OUI
AmigoCloud API AmigoCloud OUI OUI Non, nécessite la librairie libcurl
ESRI ArcObjects ArcObjects Non OUI Non, nécessite la librairie ESRI ArcObjects
Arc/Info Binary Coverage AVCBin Non OUI OUI
Arc/Info .E00 (ASCII) Coverage AVCE00 Non OUI OUI
Arc/Info Generate ARCGEN Non Non OUI
Atlas BNA BNA OUI Non OUI
AutoCAD DWG DWG Non Non Non, nécessite la librairie Open Design Alliance Teigha
AutoCAD DXF DXF OUI Non OUI
Carto Carto OUI OUI Non, nécessite la librairie libcurl
Cloudant / CouchDB Cloudant OUI OUI Non, nécessite la librairie libcurl
CouchDB / GeoCouch CouchDB OUI OUI Non, nécessite la librairie libcurl
Comma Separated Value (.csv) CSV OUI Non OUI
OGC CSW (Catalog Service for the Web) CSW Non OUI Non, nécessite la librairie libcurl
Czech Cadastral Exchange Data Format VFK Non OUI Non, nécessite la librairie libsqlite3
DB2 Spatial DB2ODBC OUI OUI Non, nécessite la librairie ODBC
DODS/OPeNDAP DODS Non OUI Non, nécessite la librairie libdap
EDIGEO EDIGEO Non OUI OUI
ElasticSearch ElasticSearch OUI OUI Non, nécessite la librairie libcurl
ESRI FileGDB FileGDB OUI OUI Non, nécessite la librairie FileGDB API
ESRI Personal GeoDatabase PGeo Non OUI Non, nécessite la librairie ODBC
ESRI ArcSDE SDE Non OUI Non, nécessite la librairie ESRI SDE
ESRI Shapefile / DBF ESRI Shapefile OUI OUI OUI
FMEObjects Gateway FMEObjects Gateway Non OUI Non, nécessite la librairie FME
GeoJSON GeoJSON OUI OUI OUI
Géoconcept Export Geoconcept OUI OUI OUI
Geomedia .mdb Geomedia Non Non Non, nécessite la librairie ODBC
GeoPackage GPKG OUI OUI Non, nécessite la librairie libsqlite3
GeoRSS GeoRSS OUI OUI OUI (la lecture nécessite la librairie libexpat)
Tables Google Fusion GFT OUI OUI Non, nécessite la librairie libcurl
GML GML OUI OUI OUI (la lecture nécessite la librairie Xerces or libexpat)
GMT GMT OUI OUI OUI
GPSBabel GPSBabel OUI OUI OUI (nécessite la librairie GPSBabel et GPX driver)
GPX GPX OUI OUI OUI (la lecture nécessite la librairie libexpat)
GRASS Vector Format GRASS Non OUI Non, nécessite la librairie libgrass
GPSTrackMaker (.gtm, .gtz) GPSTrackMaker OUI OUI OUI
Hydrographic Transfer Format HTF Non OUI OUI
Idrisi Vector (.VCT) Idrisi Non OUI OUI
Informix DataBlade IDB OUI OUI Non, nécessite la librairie Informix DataBlade
INTERLIS « Interlis 1 » et « Interlis 2 » OUI OUI Non, nécessite la librairie Xerces
INGRES INGRES OUI Non Non, nécessite la librairie INGRESS
JML OpenJUMP .jml OUI Non OUI (la lecture nécessite la librairie libexpat)
KML KML OUI OUI OUI (la lecture nécessite la librairie libexpat)
LIBKML LIBKML OUI OUI Non, nécessite la librairie libkml
Fichiers Mapinfo MapInfo File OUI OUI OUI
Microstation DGN DGN OUI Non OUI
Access MDB (PGeo et Geomedia) MDB Non OUI Non, nécessite la librairie JDK/JRE
Memory Memory OUI OUI OUI
MongoDB MongoDB OUI OUI Non, nécessite la librairie Mongo C++ client
MySQL MySQL Non OUI Non, nécessite la librairie MySQL
NAS – ALKIS NAS Non OUI Non, nécessite la librairie Xerces
NetCDF netCDF OUI OUI Non, nécessite la librairie libnetcdf
Oracle Spatial OCI OUI OUI Non, nécessite la librairie OCI
ODBC ODBC Non OUI Non, nécessite la librairie ODBC
MS SQL Spatial MSSQLSpatial OUI OUI Non, nécessite la librairie ODBC
Open Document Spreadsheet ODS OUI Non Non, nécessite la librairie libexpat
OGDI Vectors (VPF, VMAP, DCW) OGDI Non OUI Non, nécessite la librairie OGDI
OpenAir OpenAir Non OUI OUI
ESRI FileGDB OpenFileGDB Non OUI OUI
OpenStreetMap XML et PBF OSM Non OUI Non, nécessite la librairie libsqlite3 (et libexpat pour OSM XML)
PCI Geomatics Database File PCIDSK OUI OUI OUI, utilisant en interne PCIDSK SDK (de GDAL 1.7.0)
Geospatial PDF PDF OUI OUI OUI (la lecture nécessite libpoppler ou libpodofo)
PDS PDS Non OUI OUI
Planet Labs Scenes API PLScenes Non OUI Non, nécessite la librairie libcurl
PostgreSQL SQL dump PGDump OUI OUI OUI
PostgreSQL/PostGIS PostgreSQL/PostGIS OUI OUI Non, nécessite la librairie PostgreSQL client (libpq)
EPIInfo .REC REC Non Non OUI
S-57 (ENC) S57 Non OUI OUI
SDTS SDTS Non OUI OUI
SEG-P1 / UKOOA P1/90 SEGUKOOA Non OUI OUI
SEG-Y SEGY Non Non OUI
format Selafin/Seraphin Selafin OUI Partial (seulement codes EPSG) OUI
Norwegian SOSI Standard SOSI Non OUI Non, nécessite la librairie FYBA
SQLite/SpatiaLite SQLite OUI OUI Non, nécessite la librairie libsqlite3 or libspatialite
SUA SUA Non OUI OUI
SVG SVG Non OUI Non, nécessite la librairie libexpat
Storage et eXchange Format SXF Non OUI OUI
UK .NTF UK. NTF Non OUI OUI
U.S. Census TIGER/Line TIGER Non OUI OUI
VRT – Virtual Datasource VRT Non OUI OUI
OGC WFS (Web Feature Service) WFS OUI OUI Non, nécessite la librairie libcurl
MS Excel format XLS Non Non Non, nécessite la librairie libfreexl
MS Office Open XML spreadsheet XLSX OUI Non Non, nécessite la librairie libexpat
X-Plane/Flightgear aeronautical data XPLANE Non OUI OUI
VDV-451/VDV-452/IDF VDV OUI OUI OUI
Walk Walk Non OUI Non, nécessite la librairie ODBC
WAsP .map format WAsP OUI OUI OUI

 

Ensuite, nous avons introduit les deux lignes de code:

if not layer.isValid():
print « erreur de chargement de la couche %s  » % layer.name()

Si pour une raison ou pour une autre QgsVectorLayer échoue dans la création de la couche (erreur dans le nom de fichier, données corrompues, etc…) il ne renvoie pas de message d’erreur. Votre script continuera à s’exécuter et il plantera plus loin. Le message d’erreur que vous aurez a de fortes chances de ne rien avoir avec le véritable problème. Il convient donc de tester la validité de chaque couche créée et d’afficher l’erreur immédiatement.

En fin, dans la dernière ligne, nous ajoutons la couche vectorielle à l’QgsMapLayerRegistry, ce qui la rend disponible et visible sur la carte.

QgsMapLayerRegistry.instance().addMapLayers([layer])

Le registre conserve la trace de toutes les couches du projet. La raison pour laquelle QGIS fonctionne de cette façon est pour vous permettre de charger plusieurs couches, leur affecter un style , les filtrer, ainsi que plusieurs autres opérations, avant de les afficher sur la carte.

 Coder le choix du fichier à charger

Dans notre code, le fichier à charger est écrit en dur, ce qui est rarement le cas dans la réalité des développements. Nous allons voir comment coder la recherche du fichier avec la fenêtre »ouvrir un fichier » .

Dans scriptrunner créez un nouvel script dialogue_fichier.py.

Rentrez le code suivant

# Customize this starter script by adding code
# to the run_script function. See the Help for
# complete information on how to create a script
# and use Script Runner.

«  » » Your Description of the script goes here «  » »

# Some commonly used imports

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *

def run_script(iface):
qfd = QFileDialog()
title = ‘Ouvrir un fichier’
path = « C:/ »
f = QFileDialog.getOpenFileName(qfd, title, path)
print f

Votre script doit ressembler à ça:

pv7Quand vous l’exécutez, il affiche la fenêtre de recherche de fichiers. Quand vous cliquez sur « Ouvrir », le script vous affiche le nom complet de votre fichier.

La ligne from PyQt4.QtGui import * est indispensable pour pouvoir appeler le dialogue.

QFileDialog utilise trois paramètres:

  • l’objet QFileDialog : qfd
  • le titre de la fenêtre du dialogue: title
  • le chemin de départ de la fenêtre : dans cet exemple C:/ (mais vous pouvez indiquer n’importe quel répertoire)

Le résultat (f) contient une chaîne de caractères avec le chemin et nom du fichier sélectionné. Si l’utilisateur ne clique pas sur Ouvrir mais sur Annuler, la chaîne est vide.

Nous pouvons maintenant modifier le premier script (chargement d’un shape) pour utiliser le dialogue à la place du codage en dur:

pv8A l’exécution du script, la fenêtre de dialogue s’ouvre, vous choisissez le fichier à charger, puis le script le charge dans QGis.

Dans le prochain article nous verrons comment faire la même chose mais à partir d’une table Postgis  ou d’une base de données Spatialite.

 

Si cet article vous a intéressé et que vous pensez qu'il pourrait bénéficier à d'autres personnes, n'hésitez pas à le partager sur vos réseaux sociaux en utilisant les boutons ci-dessous. Votre partage est apprécié !

7 thoughts on “Recettes Python pour QGis: accéder aux données vecteur(shapefile)

  1. Bonjour,
    Je ne parviens pas utiliser QFileDialog: « NameError: name ‘QFileDialog’ is not defined ». Je suis sous QGIS3.8, ScritRunnerV3.0.5, MacOSX10.13.6. J’ai modifié les imports en :
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from qgis.core import *
    from qgis.gui import *
    .. mais QFileDialog ne fonctionne toujours pas.
    Avez-vous une idée ?
    Merci !

      1. La variable f retourne un type ‘tuple’ désormais : TypeError: QgsVectorLayer(): argument 1 has unexpected type ‘tuple’. C’est vraiment dommage toutes ces modifications de comportement entre les versions d’objet. Votre tutoriel n’est pourtant pas si vieux !

        1. J’ai donc modifié QgsVectorLayer(f, »Mon fichier », »ogr ») par QgsVectorLayer(f[0], »Mon fichier », »ogr ») et ça marche.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *