Exemple de script Python utilisant QGIS sans l’ouvrir graphiquement

Cherchant à comprendre les bases de l’utilisation de Python et QGIS, j’ai voulu faire un script très simple qui liste les noms des entités dans un Shapefile sans lancer QGIS.

Il y a en effet trois façons d’utiliser Python avec QGIS.
- Dans la console Python de QGIS.
- En réalisant une extension à QGIS en Python.
- Dans un script Python qu’on exécutera hors de QGIS et qui fera appel à l’API de ce dernier.

C’est de cette troisième méthode qu’il est question ici.

J’ai été surpris d’avoir beaucoup de mal à trouver dans les documentations comment faire un script simple qui ouvre un shapefile. Je garde donc cet exemple (même s’il est minimal et codé à la va-vite) en guise d’aide-mémoire.

Ce script fonctionne sous Debian Wheezy. Selon votre système d’exploitation, la ligne QgsApplication.setPrefixPath(‘/usr’, True) est à adapter. C’est le truc pénible à trouver dans les docs.

Mise à jour du 12 mai 2015 :
Ajout d’une ligne pour afficher correctement les caractères accentués si le fichier est en UTF-8.

Mise à jour du 29 juin 2015 :
Ajout de deux lignes en début de script, pour résoudre un problème apparu depuis la dernière mise à jour de QGIS. Voir détails ici.

from qgis.core import *
from qgis.gui import *
import os
import sys

from PyQt4.Qt import *
app = QApplication(sys.argv)

# S'il n'y a pas deux arguments (nom du script + nom d'un fichier), 
# on affiche un message et on ferme.
if len(sys.argv) != 2:
	print "USAGE : python " + sys.argv[0] + " shapefile name"
	exit(1)

# Nom complet (avec chemin) du fichier a ouvrir = repertoire courant + argument.
# Note : il faudrait faire un truc plus propre que ca pour gerer aussi les chemins absolus aussi.
fichier = os.getcwd() + '/' + sys.argv[1]

# Important : a mettre obligatoirement a cet endroit et surtout pas apres le initQgis... Que de temps perdu a cause de ca !
QgsApplication.setPrefixPath('/usr', True)  

# Initialisation de QGIS.
QgsApplication.initQgis()

# Decommenter ceci pour afficher la configuration de QGIS.
# print QgsApplication.showSettings()

# On informe l'utilisateur de l'ouverture du fichier.
print "Opening file " + fichier

# On l'ouvre.
layer = QgsVectorLayer(fichier, "layer_name", "ogr")

# On teste sa validite. S'il n'est pas valide, on ferme.
if not layer.isValid():
	print "Layer didn't load properly."
	print "Check your filename and the file integrity."
	exit(2)

# ajout indispensable si votre fichier est en UTF-8
layer.setProviderEncoding(u'UTF-8')
# On informe l'utilisateur.
print "File successfully loaded as " + layer.name() + " layer."

# On cherche a savoir quelle est la position du champ non dans la table attributaire.
idnom = layer.fieldNameIndex('NOM')

# On l'affiche.
print "Field 'NOM' is field #", idnom, " in attribute table."

# On parcourt la table d'attributs de tout le shapefile pour lister les noms.
provider = layer.dataProvider()
i = 0
for toto in provider.getFeatures():
        print i, toto.attributes()[idnom]
	i += 1

QgsApplication.exitQgis()
Ce contenu a été publié dans Astuces, Informatique. Vous pouvez le mettre en favoris avec ce permalien.

22 réponses à Exemple de script Python utilisant QGIS sans l’ouvrir graphiquement

  1. Etienne dit :

    Intéressant ;-)
    Je ne savais même pas, mais cela sera bientôt dans mon stage.

    Mais sortir QGIS pour çà, c’est un peu « écraser une mouche avec un bulldozer » :)
    Il existe l’api OGR de GDAL (QGIS s’appuie dessus pour ouvrir le shape), Fiona, Shapely…

    • Adrien dit :

      Tu sais, quand tu programmes un « Hello world » en C, tu écrases aussi une mouche avec un bulldozer puisqu’il t’aurait suffi d’écrire « Hello world » à la main dans ton terminal…

      Mais le principe d’un exemple, c’est… d’être un exemple. À partir de cet exemple, tu peux lancer toutes les fonctions de QGIS et faire des traitements SIG sur les données. Par exemple, des buffers…

  2. Etienne dit :

    Oups pardon, j’avais lu un peu vite l’article.

    Le coup du buffer est aussi possible directement dans chacune des libs ;-)

  3. Marouane dit :

    Merci beaucoup pour cet exemple, je cherchais justement comment faire cela! Je débute un peu sur Qgis et Python, et des petits guides comme celui là me sont très utiles, merci :)

    • Adrien dit :

      Content que ça serve. :)

      J’ai mis du temps à trouver l’ensemble des fonctions utilisées. Alors si je peux faire gagner du temps à d’autres, tant mieux. :)

  4. pierre PIMA dit :

    vraiment très salvateur votre script
    maintenant puis savoir ou trouver ses fonctions ?
    merci c’est trop top

  5. Mélanie dit :

    Bonjour,

    J’ai voulu essayé en utilisant le bloc notes, mais cela n’a effectivement pas marché. Est-on obligé de télécharger Debian Wheezy? Auriez-vous des solutions avec les deux précédentes méthodes que vous citez:
    - Dans la console Python de QGIS.
    - En réalisant une extension à QGIS en Python.

    Merci encore pour cette exemple.

    • Adrien dit :

      L’exemple donné fonctionne sous Debian Wheezy, et probablement Ubuntu aussi.

      Après, si vous voulez travailler sous Windows, il faudra l’adapter (notamment au niveau des chemins d’accès : « /usr » est spécifique aux systèmes Unix).

      Mais vous cherchez à faire quoi, exactement ? Mon exemple n’a pas d’autre but que d’expliquer comment utiliser QGIS et Python depuis la console Linux, et visiblement vous êtes sous Windows et cherchez à faire quelque chose dans QGIS avec Python mais je ne sais pas quoi.

  6. kerplouz dit :

    Merci pour ce tuto..
    Testé sous windows 7 je prends un:

    from qgis.core import *
    ImportError: No module named qgis.core

    Au départ… Une idée de la cause de l’erreur ?

    • Adrien dit :

      C’est sans doute une histoire de chemin d’accès aux modules Python pour QGIS. Je trouverais probablement la solution si j’avais votre machine sous la main, mais à distance je n’en suis pas capable sous Windows.

  7. Anna dit :

    Bonjour,
    je voudrais créer un script me permettant de lire dans un fichier csv les colonnes et de trouver les valeurs les plus proches inférieures et supérieures.
    Avez vous une idée?
    Je voulais d’abord faire un tri croissant et enregistrer la valeur juste inférieure. puis un tri décroissant et enregistrer la valeur supérieure. Mais sur QGIS je n’arrive pas à la faire.

    Merci

    • Adrien dit :

      Je ne suis pas sûr de vraiment comprendre ce que vous voulez faire. Peut-être faut-il utiliser d’autres outils (la commande sort sous Unix / Linux, ou un tableur).

  8. PELLET Alexandre dit :

    Bonjour Adrien,

    Sympa le script.

    Y a-t-il un moyen pour lancer QGIS via ce script, afficher sa fenêtre et charger des couches pour les afficher, un peu comme le qgis browser?
    Merci

    Alexandre

    • Adrien dit :

      Via ce script, clairement, non. Il est justement fait pour ne pas ouvrir QGIS graphiquement.

      Par contre, peut-être qu’il existe des options à passer au lancement de QGIS pour qu’il s’ouvre graphiquement et affiche certaines couches. Je ne sais pas. Il faut chercher.

  9. Léopold dit :

    Bonjour,
    Je suis en stage de deuxième année d’école d’ingé et je dois développer un script utilisant les fonctions de QGIS hors de QGIS.
    Je dispose de deux versions de QGIS : une « 2.4″ et une « 2.14.15″.
    Pour ce qui est de python je tourne avec Anaconda 3 et un python 3.6.
    Mais je n’arrive pas a importer le module qgis.core, j’essaie de lancer cette commande avant de lancer spyder  » set PYTHONPATH=c:\qgispath\python » (avec l’emplacement de qgis) et de mettre l’emplacement de travail de spyder à ce même endroit ; mais sans sucé. Je tombe encore et encore je l’erreur « no module named ‘qgis’ « .
    Quelqu’un aurait-il une solution ?
    Merci d’avance.

  10. svear dit :

    Bonjour

    Je suis assez familier de Python et Qt… mais on m’a donné un projet de carto et là je débute.
    C’est pourquoi je te remercie de cet exemple qui va pouvoir m’aider à démarrer.

    Si j’osais, je te recommanderais de remplacer
    fichier = os.getcwd() + ‘/’ + sys.argv[1]
    par
    fichier = os.path.join(os.getcwd() , sys.argv[1])
    plus portable (le séparateur, qui diffère sous zindow, est justement positionné par rapport à l’OS)

    Et la séquence
    i = 0
    for toto in provider.getFeatures():
    print i, toto.attributes()[idnom]
    i += 1

    Par
    for (toto, i) in enumerate(provider.getFeatures(), 1)
    print i, toto.attributes()[idnom]
    Puisque « enumerate » sert justement à associer un compteur et un itérable. Et éventuellement remplacer « toto » par un nom plus « professionnel »…

    Cordialement

    • Adrien dit :

      Super. Merci pour ces deux astuces que je ne connaissais pas. Je ne connais pas vraiment Python, en fait. J’arrive à programmer avec car c’est un langage simple et parce qu’on trouve beaucoup de choses déjà écrites sur internet. Mais ça, c’est typiquement le genre de trucs que j’ignore, alors merci.

  11. asma dit :

    bonjour
    je dois développer un script pour ajouter un menu En QGis…..
    Quelqu’un aurait-il une solution ?
    Merci d’avance.

  12. Th Braun dit :

    Merci Adrien !
    je code des progs en python pour ArcGis et pour QGIS il me manquait un exemple de ce type pour me mettre le pied à l’étrier.

    Dans ArcGis il est possible d’utiliser le ModelBuilder pour faire ce premier pas, je n’ai pas trouvé l’équivalent dans QGIS (la sauvegarde de modèle QGIS ne produit pas de code assimilable facilement).

    Donc merci beaucoup pour ce partage

Répondre à Adrien Annuler la réponse.

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

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>