Découverte de la console Python dans QGIS
Ce 1er chapitre est inspiré de l'excellent site qgistutorials.
Ouvrez les couches peaks et eau (jointes en bas de cet article) dans un projet QGIS, ainsi que la console Python du logiciel (un bouton à cet effet est disponible dans le menu QGIS).
La couche de points en premier plan, le linéaire en second, avec une symbologie évidente. Ce sont les principaux sommets des Écrins et le réseau hydrographique français*.
* Les sommets sont issus d'une rapide extraction depuis OSM, et le réseau hydrographique est une couche IGN peu à jour. Les sommets sont encodés en UTF-8, pour bien lire les accents, précisez-le éventuellement dans QGIS. Pour augmenter les difficultés, ces 2 couches sont dans des projections différentes.
Sélectionnez la couche de points dans le panneau calque de QGIS, puis dans la console Python entrez :
layer = iface.activeLayer()
Vous venez de créer une variable arbitrairement nommée layer
et contenant la couche active (celle que vous avez sélectionnée dans QGIS).
iface
est une variable globale, qui n'est autre que le canvas courant de votre projet QGIS, les données visibles dans votre projet. Vous n'avez pas créé cette variable vous-même, mais elle s'est automatiquement créée à l'ouverture de QGIS.
activeLayer
est une méthode de Python, une action à réaliser, qui ici va chercher la couche active de votre projet. Nous reviendrons bientôt sur le point (.
) une fois que les conditions de notre compréhension seront plus explicites.
Votre 1ère variable existe donc déjà, et vous pouvez en connaître le contenu simplement puisque :
layer
Vous renverra quelques informations sur le contenu de cette variable :
<QgsMapLayer: 'peaks' (ogr)>
Vous venez de lire (d'un point de vue système) le contenu de la variable. Si vous sélectionnez maintenant la couche linéaire, et lancez les mêmes commandes, vous lirez bien-entendu un contenu différent pour la même variable. En effet elle contiendra autre chose, la méthode activeLayer
allant chercher la couche sélectionnée dans QGIS. Bienvenue dans Python pour QGIS !
Astuce
Depuis la console, nul besoin de retaper les mêmes commandes déjà utilisées. Utilisez la flèche ↑ (flèche du haut) de votre clavier pour remonter la liste des commandes exécutées. Vous pouvez également tester de lancer vos commandes depuis l'éditeur Python de QGIS (survolez les boutons disponibles en haut de la console Python de QGIS, l'éditeur s'ouvrira à droite de la console). Une interprêtation plus rigoureuse du code est à l'œuvre depuis l'éditeur Python, avec un comportement parfois un peu différent. Dans le cas de nos 2 commandes ci-dessus par exemple, il faudra ajouter un print
pour lire la couche visée.
Vous pouvez aussi interroger les quelques 500 méthodes disponibles pour cet objet :
dir(layer)
Ci-dessus, la variable layer
est soumise en tant que paramètre (ce mot n'est pas anodin en programmation) de la fonction dir
, entre parenthèse. La fonction sait donc sur quoi s'appliquer.
L'une des méthodes disponibles ets la méthode fields()
, nous pouvons consulter toutes ces options sur la documentation officielle pyqgis :
https://qgis.org/pyqgis/3.0/core/other/QgsFields.html
Exemples :
Compter le nombre de champs
layer.fields().count()
Afficher les noms des champs
layer.fields().names()
Les listes
La méthode names()
nous renvoie les champs entre crochets, c'est donc une liste (ce mot n'est pas anodin en programmation).
Nous pouvons accéder aux élements indicés des listes en ajoutant [NUMÉRO DE L'INDICE]
. Pour afficher le 1er champ par exemple :
layer.fields().names()[0]
Astuce
Les éléments d'une liste sont ordonnés de 0 à X, le 1er élément ayant toujours le numéro 0. Comme en histoire, quand nous sommes en 50 après JC, nous sommes au 1er siècle après JC. Et quand nous avons 20 ans, nous sommes dans notre 21ème année.
Boucle et itération
L'une des méthodes disponibles pour nos couches s'appelle getFeatures
. Nous allons nous en servir pour boucler sur les 341 entités contenues dans la couche de points :
layer = iface.activeLayer() for f in layer.getFeatures(): print(f['name'], f['osm_id'])
Le mot-clé for
signifie que nous démarrons une boucle. Chaque contenu de cette boucle sera stocké dans une variable f
(arbitrairement nommée ainsi, mais correspondant à une convention Python, entre autre). Le in
regarde où lancer la boucle : sur les entités contenues dans notre variable.
Et qu'est-ce que nous y lancerons ? Des instructions itératives.
Astuce
Si à ce stade la boucle ne s'est pas exécutée, c'est que vous devez sortir de la boucle, en tapant sur la touche ↵ (Entrée).
Cheminement
Dans la 2ème ligne notamment, remarquez l'usage du point (.
), qui concatène variables et instructions Python (là ou PHP concatène les chaînes).
Ce n'est donc plus une simple concaténation, mais plutôt le signe d'un cheminement du code : Python voit votre variable layer
, mais étant suivie d'un .
il sait qu'il y a quelque chose à faire dessus. Quoi donc ? Y lancer la méthode qui suit.
Mais au fait, si le point sert à Python pour concaténer des instructions, comment concatène-t-il les chaînes de texte ? Avec le signe +
.
Indentation
Observez l'indentation devant la 3ème ligne. L'indentation est partie intégrante du langage Python, elle permet de structurer son code et plus encore, de signifier des choses dans le code.
Ici l'indentation précédant le print
signifie qu'il est physiquement contenu dans la boucle.
L'indentation a donc son rôle à jouer. Avec Python une mauvaise indentation soulèvera une erreur d'exécution (cela contrairement à PHP, où l'indentation n'est là que pour aider à la lecture, au mieux).
Après saisie complète du code ci-dessus dans la console, pour exécuter la boucle, il vous faudra taper une dernière fois sur ↵ (Entrée) , pour sortir de la boucle. Les noms des principaux sommets de la zone de glaciers des Écrins, et leur identifiant OSM, défilent dans la fenêtre de résultats.
Astuce
Une erreur courante est parfois soulevée, suite à des copier-coller ou des modifications du code depuis un autre logiciel :
<span style="color: #ff0000; font-size: 10pt;">Inconsistent use of tabs and spaces in indentation.</span>
Le log est explicite : il s'agit d'un mélange de tabulations et d'espaces dans votre indentation. Visuellement votre code est propre, mais pas pour la machine, qui voit TOUT. En effet si vous avez commencé par utiliser des espaces ou des tabulations pour indenter, alors vous devez vous y tenir. De même si vous utilisez des indentation à 2 espaces, alors 2 indentations feront 4 espaces ; si vous faîtes des indentations à 4 espaces, alors 2 indentations feront 8 espaces. Souvenez-vous en pour la suite de ce tutoriel !
Corrigez donc la ligne concernée et prenez de bonnes habitudes : Notepad possède un paramètre pour signifier quel caractère systématiquement utiliser dans les indentations de la touche Tab du clavier.
1ère fonction géométrique
De même que nous affichons les noms des sommets, nous pouvons les géocoder, en listant leurs coordonnées géographiques (xy) :
for f in layer.getFeatures(): geom = f.geometry() print(geom.asPoint())
Astuce
Si à ce stade la boucle ne s'est pas exécutée, c'est que vous devez sortir de la boucle, en tapant sur la touche ↵ (Entrée).
Nous avons cette fois créé une variable directement dans notre boucle (f
).
La méthode geometry
récupère certaines des informations spatiales de nos entités, toutes stockées et bien organisées dans notre variable geom
, même si nous ne les voyons pas.
Puis le print
interroge notre variable sur l'un de ses contenus, asPoint
, méthode qui récupére les latitudes et longitudes.
- Note personnelle : extraire un réseau hydrographique plus complet depuis OSM, ainsi que les sommets tagués différemment (les pointes par exemple).