Recettes Python pour QGis: accéder aux données vecteur (postgis,spatialite)

Dans cette série d’articles nous abordons comment accéder aux données de type vecteur avec Python et QGis. Tout d’abord nous avons vu dans l’article précédent (Recettes Python pour QGis: accéder aux données vecteur (shapefile)) comment charger un fichier shapefile. Dans celui-ci nous verrons comment charger une table Postgresql/Postgis et une table Spatialite.

Charger une couche Postgis

L’autre source de données habituelle pour une application QGis est une couche vecteur contenue dans une base de données Postgres/Postgis. Nous allons voir comment la charger à partir du code Python.

Le principe est le même que pour une couche shapefile, sauf que nous allons utiliser un autre fournisseur de données (data provider) et que, contrairement à un fichier shp, il faut créer la connexion à la base de données.

Dans ScripRunner créez un nouveau script et nommez-le charger_database.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):
uri = QgsDataSourceURI()
uri.setConnection(« localhost », « 5432 », « postgres », »user1″, « user1 »)
uri.setDataSource(« public », « details », « geom », »version=1″)
layer = QgsVectorLayer(uri.uri(), « Recifs », « postgres »)
if not layer.isValid():
print « Layer %s did not load » % layer.name()
QgsMapLayerRegistry.instance().addMapLayers([layer])

Le script doit ressembler à ça:

pv10Vous observerez que la ligne de code qui crée le layer

layer = QgsVectorLayer(uri.uri(), « Recifs », « postgres »)

contient un fournisseur postgres à la place de ogr et que le nom de fichier est remplacé par un objet uri. C’est cet objet qui est en charge de la connexion avec la base Postgis.

uri = QgsDataSourceURI()

crée l’objet,

uri.setConnection(« localhost », « 5432 », « postgres », »user1″, « user1 »)

crée la chaîne de connexion:

  • adresse du serveur (ici localhost)
  • port d’écoute de postgres (ici 5432)
  • nom de la base de données(ici postgres)
  • nom de l’utilisateur (ici user1)
  • mot de passe de l’utilisateur (ici user1)

Si vous voulez exécuter le script sur votre machine, vous devez modifier ces valeurs pour celles d’une base de données existante sur votre poste (si vous gardez localhost) ou rentrer une adresse de base accessible par Internet.

uri.setDataSource(« public », « details », « geom », »version=1″)

Cette ligne défini quelles table Postgis utiliser dans la base de données connectée:

  • nom du schéma (ici public)
  • nom de la table (ici details)
  • nom du champ géométrie de la table (ici geom)
  • éventuellement une clause SQL de type WHERE.

Ici version=1 correspond à une clause

SELECT * FROM details WHERE version=1

Si vous ne voulez pas appliquer un filtre à la table, rentrez simplement «  ».

Charger une couche Spatialite

Trop peu utilisées et pourtant tellement pratiques et puissantes, les bases Spatialite peuvent aussi être chargées simplement avec Python.

Voici le code pour un script comparable au précédent mais qui charge une table d’une base Sopatialite:

# 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):
uri = QgsDataSourceURI()
uri.setDatabase(« H:/repertoiresblog/QGis/validation.sqlite »)
uri.setDataSource(«  », « com2011orig », « geom », »cod_reg=9″)
layer = QgsVectorLayer(uri.uri(), « Communes », « spatialite »)
if not layer.isValid():
print « Layer %s did not load » % layer.name()
QgsMapLayerRegistry.instance().addMapLayers([layer])

Votre script doit ressembler à ça:

pv11uri.setDatabase(« H:/repertoiresblog/QGis/validation.sqlite »)

Cette ligne défini le chemin et nom de la base Spatialite concernée.

  uri.setDataSource(«  », « com2011orig », « geom », »cod_reg=9″)

Le premier paramètre, schéma, ne s’applique pas aux bases Spatialite.

  • nom de la table à charger (ici com2011orig)
  • nom du champ géométrie (ici geom)
  • clause de filtrage SQL, optionnelle (ici cod_reg=9)

 layer = QgsVectorLayer(uri.uri(), « Communes », « spatialite »)

On crée la couche avec l’objet uri que nous venons de construire et nous faisons appel au fournisseur de données spatialite.

Les autres fournisseurs de données disponibles

Nous avons vu trois fournisseurs de données pour QgsVectorLayer: ogr, postgres, et spatialite. Le premier est en réalité une bibliothèque qui permet l’accès à de nombreux formats.

En plus de ces trois fournisseurs, vous pouvez utiliser les suivants:

  • memory qui permet de charger des couches créées en mémoire
  • mssql qui permet de charger une couche d’une base Microsoft SQL
  • wfs qui permet de charger une couche d’un flux WFS
  • delimitedtext qui permet de charger une couche à partir d’un fichier texte
  • gpx qui charge des routes et des waypoints à partir d’un fichier gpx
  • grass qui charge une couche GRASS

Dans l’article suivant nous verrons comment consulter les attributs et les géométries des couches vecteur chargée dans QGis.

7 réponses sur “Recettes Python pour QGis: accéder aux données vecteur (postgis,spatialite)”

  1. Bonjour, Merci de votre tuto

    J’essaie de me connecter a ma bdd postgis avec QGIS3 avec les changements apporté a cette version, mais quand je fais run ma fonction mon QGIS bug et se ferme, saviez vous quelle est la raison.

    Merci

    1. Je ne comprends peut-être pas la question, mais qu’est-ce que vous voulez exécuter? N’oubliez pas que la version de Python de QGis 3 est Python 3 tandis que la version utilisée par QGis 2 était Python 2

      1. Merci Atlllo,

        Je sais par rapport aux version et j’ai donc effectué les modifications nécessaires.
        en revanche quand j’excute la fonction ca me met sur QGIS « couche inutilisable » je pourrais vous mettre mon script pour voir l’eventuelle erreur.

        uriPG = QgsDataSourceUri()
        uriPG.setConnection(« localhost », « 5432 », « Base_test », « Nassim », « ****** »)

        uriPG.setDataSource(« public », « BPE », « geom », » »)
        layer = QgsVectorLayer(uriPG.uri(), « BPE »)
        if not layer.isValid():
        print(« Layer %s did not load » %layer.name())
        QgsProject.instance().addMapLayer(layer

        Merci

        1. Je ne sais pas si c’est un problème récent ou ancien, mais en tout cas, la géométrie de la table postgres doit être définie. On peut charger manuellement une table sans src dans QGis, mais le driver python considère la couche inutilisable si c’est le cas.

  2. Bonjour je suis novice (++++) en python qgis (je n’ai jamais utilisé script runner) et j’ai essayé de charger une couche Spatialite à l’aide de votre script.

    mon script adapté :

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

    def run_script(iface):
    uri = QgsDataSourceURI()
    uri.setDatabase(« C:/bckup/dev/admin/QGIS/Fond_de_carte/client.sqlite »)
    uri.setDataSource(«  », »porte_feuille_client », »geom », » »)
    layer = QgsVectorLayer(uri.uri(), »clients », « spatialite »)
    QgsMapLayerRegistry.instance().addMapLayers([layer])

    Dès lors j’ai une erreur qui s’affiche :

    invalid syntax (testbis.py, line 32)
    (au passage ligne 32 qui n’existe pas, peu être manque t il un point virgule tout simplement ….)

    Ainsi qu’une erreur dans la console :

    Running testbis.py in: C:/bckup/dev/admin/QGIS/Python
    user_args type:
    iface type:
    Completed script: testbis.py

    C’est peu être tout bête mais c’est vrai qu’étant débutante, c’est compliqué.

    Merci d’avance pour votre réponse

Laisser un commentaire

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