3. Chargement de couches

Les extraits de code sur cette page nécessitent les importations suivantes :

import os # This is is needed in the pyqgis console also
from qgis.core import (
    QgsVectorLayer
)

Ouvrons donc quelques couches de données. QGIS reconnaît les couches vectorielles et raster. En plus, des types de couches personnalisés sont disponibles mais nous ne les aborderons pas ici.

3.1. Couches vectorielles

Pour créer et ajouter une instance de couche vecteur au projet, il faut spécifier l’identifiant de la source de données de la couche, le nom de la couche et le nom du provider :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# get the path to the shapefile e.g. /home/project/data/ports.shp
path_to_airports_layer = "testdata/airports.shp"

# The format is:
# vlayer = QgsVectorLayer(data_source, layer_name, provider_name)

vlayer = QgsVectorLayer(path_to_airports_layer, "Airports layer", "ogr")
if not vlayer.isValid():
    print("Layer failed to load!")
else:
    QgsProject.instance().addMapLayer(vlayer)

L’identifiant de source de données est une chaîne de texte, spécifique à chaque type de fournisseur de données vectorielles. Le nom de la couche est utilisée dans le widget liste de couches. Il est important de vérifier si la couche a été chargée ou pas. Si ce n’était pas le cas, une instance de couche non valide est retournée.

Pour une couche vectorielle geopackage:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# get the path to a geopackage  e.g. /usr/share/qgis/resources/data/world_map.gpkg
path_to_gpkg = os.path.join(QgsApplication.pkgDataPath(), "resources", "data", "world_map.gpkg")
# append the layername part
gpkg_countries_layer = path_to_gpkg + "|layername=countries"
# e.g. gpkg_places_layer = "/usr/share/qgis/resources/data/world_map.gpkg|layername=countries"
vlayer = QgsVectorLayer(gpkg_countries_layer, "Countries layer", "ogr")
if not vlayer.isValid():
    print("Layer failed to load!")
else:
    QgsProject.instance().addMapLayer(vlayer)

La méthode la plus rapide pour ouvrir et afficher un couche vectorielle dans QGIS est addVectorLayer() de la classe QgisInterface:

vlayer = iface.addVectorLayer(path_to_airports_layer, "Airports layer", "ogr")
if not vlayer:
  print("Layer failed to load!")

Cela crée une nouvelle couche et l’ajoute au projet QGIS courant (la faisant apparaître dans la liste des couches) en une seule étape. Cette fonction renvoie une instance de la couche ou None si la couche n’a pas pu être chargée.

La liste suivante montre comment accéder à différentes sources de données provenant de différents fournisseurs de données vectorielles:

  • la bibliothèque OGR (shapefile et de nombreux autres formats de fichiers) — La source de données est le chemin vers le fichier:

    • pour un shapefile:

      vlayer = QgsVectorLayer("testdata/airports.shp", "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
    • pour un dxf (notez les options internes dans l’uri de la source de données) :

      uri = "testdata/sample.dxf|layername=entities|geometrytype=Polygon"
      vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
  • Base de données PostGIS - La source de données est une chaîne de caractères data source contenant toute l’information nécessaire pour établir une connexion avec la base PostgreSQL.

    La classe QgsDataSourceUri peut générer cette chaîne de caractères pour vous. Notez que QGIS doit être compilé avec le support postgreSQL, faute de quoi le fournisseur ne sera pas disponible:

    1
    2
    3
    4
    5
    6
    7
    8
    uri = QgsDataSourceUri()
    # set host name, port, database name, username and password
    uri.setConnection("localhost", "5432", "dbname", "johny", "xxx")
    # set database schema, table name, geometry column and optionally
    # subset (WHERE clause)
    uri.setDataSource("public", "roads", "the_geom", "cityid = 2643", "primary_key_field")
    
    vlayer = QgsVectorLayer(uri.uri(False), "layer name you like", "postgres")
    

    Note

    L’argument False passé à uri.uri(False) empêche l’expansion des paramètres du système d’authentification. si vous n’avez pas configuré d’authentification, cet argument n’a aucun effet.

  • fichiers CSV et autres fichiers avec délimiteurs —Pour ouvrir un fichier avec des points virgules comme séparateurs, contenant des champs « x » pour les coordonnées X et « y » pour les coordonnées Y, vous devriez faire ceci:,

    uri = "file://{}/testdata/delimited_xy.csv?delimiter={}&xField={}&yField={}".format(os.getcwd(), ";", "x", "y")
    vlayer = QgsVectorLayer(uri, "layer name you like", "delimitedtext")
    QgsProject.instance().addMapLayer(vlayer)
    

    Note

    La chaîne de texte du fournisseur de données est structuré comme une URL, le chemin doit ainsi être préfixé avec file://. Il permet aussi d’utiliser les géométries formatées en WKT (well-known text) à la place des champs x et y, et permet de spécifier le Système de Coordonnées de Référence. Par exemple :

    uri = "file:///some/path/file.csv?delimiter={}&crs=epsg:4723&wktField={}".format(";", "shape")
    
  • Fichiers GPS — le fournisseur de données « gpx » lit les trajets, routes et points de passage d’un fichier gpx. Pour ouvrir un fichier, le type (trajet/route/point) doit être fourni dans l’url :

    uri = "testdata/layers.gpx?type=track"
    vlayer = QgsVectorLayer(uri, "layer name you like", "gpx")
    QgsProject.instance().addMapLayer(vlayer)
    
  • Base de données spatialite — De manière similaire aux bases de données PostGIS, QgsDataSourceUri peut être utilisé pour générer l’identifiant de la source de données:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    uri = QgsDataSourceUri()
    uri.setDatabase('/home/martin/test-2.3.sqlite')
    schema = ''
    table = 'Towns'
    geom_column = 'Geometry'
    uri.setDataSource(schema, table, geom_column)
    
    display_name = 'Towns'
    vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')
    QgsProject.instance().addMapLayer(vlayer)
    
  • Géométries MySQL basées sur WKB, avec OGR — la source des données est la chaîne de connexion à la table :

    uri = "MySQL:dbname,host=localhost,port=3306,user=root,password=xxx|layername=my_table"
    vlayer = QgsVectorLayer( uri, "my table", "ogr" )
    QgsProject.instance().addMapLayer(vlayer)
    
  • Connexion WFS : la connexion est définie avec un URI et en utilisant le fournisseur WFS :

    uri = "https://demo.geo-solutions.it/geoserver/ows?service=WFS&version=1.1.0&request=GetFeature&typename=geosolutions:regioni"
    vlayer = QgsVectorLayer(uri, "my wfs layer", "WFS")
    

    L’uri peut être crée en utilisant la bibliothèque standard urllib:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    import urllib
    
    params = {
        'service': 'WFS',
        'version': '1.1.0',
        'request': 'GetFeature',
        'typename': 'geosolutions:regioni',
        'srsname': "EPSG:4326"
    }
    uri2 = 'https://demo.geo-solutions.it/geoserver/ows?' + urllib.parse.unquote(urllib.parse.urlencode(params))
    

Note

Vous pouvez changer la source de données d’une couche existante en appelant setDataSource() sur une instance QgsVectorLayer, comme dans l’exemple suivant :

1
2
3
4
5
6
7
uri = "https://demo.geo-solutions.it/geoserver/ows?service=WFS&version=1.1.0&request=GetFeature&typename=geosolutions:regioni"
provider_options = QgsDataProvider.ProviderOptions()
# Use project's transform context
provider_options.transformContext = QgsProject.instance().transformContext()
vlayer.setDataSource(uri, "layer name you like", "WFS", provider_options)

del(vlayer)

3.2. Couches raster

Pour accéder aux fichiers raster, la bibliothèque GDAL est utilisée. Elle prend en charge un large éventail de formats de fichiers. Si vous avez des difficultés à ouvrir certains fichiers, vérifiez si votre GDAL prend en charge le format en question (tous les formats ne sont pas disponibles par défaut). Pour charger un raster à partir d’un fichier, indiquez son nom de fichier et son nom d’affichage :

1
2
3
4
5
# get the path to a tif file  e.g. /home/project/data/srtm.tif
path_to_tif = "qgis-projects/python_cookbook/data/srtm.tif"
rlayer = QgsRasterLayer(path_to_tif, "SRTM layer name")
if not rlayer.isValid():
    print("Layer failed to load!")

Pour charger un raster à partir d’un géopackage :

1
2
3
4
5
6
7
8
9
# get the path to a geopackage  e.g. /home/project/data/data.gpkg
path_to_gpkg = os.path.join(os.getcwd(), "testdata", "sublayers.gpkg")
# gpkg_raster_layer = "GPKG:/home/project/data/data.gpkg:srtm"
gpkg_raster_layer = "GPKG:" + path_to_gpkg + ":srtm"

rlayer = QgsRasterLayer(gpkg_raster_layer, "layer name you like", "gdal")

if not rlayer.isValid():
    print("Layer failed to load!")

Tout comme les couches vecteur, les couches raster peuvent être chargées en utilisant la fonction addRasterLayer de l’objet QgisInterface :

iface.addRasterLayer(path_to_tif, "layer name you like")

Cela crée une nouvelle couche et l’ajoute au projet en cours (en la faisant apparaître dans la liste des couches) en une seule étape.

Pour charger un raster PostGIS :

Les raster PostGIS, similaires aux vecteurs PostGIS, peuvent être ajoutées à un projet en utilisant une chaîne URI. Il est efficace de conserver un dictionnaire de chaînes réutilisable pour les paramètres de connexion à la base de données. Il est ainsi facile de modifier le dictionnaire pour la connexion applicable. Le dictionnaire est ensuite encodé dans une URI en utilisant l’objet de métadonnées du fournisseur “postgresraster”. Ensuite, le raster peut être ajouté au projet.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
uri_config = {
    # database parameters
    'dbname':'gis_db',      # The PostgreSQL database to connect to.
    'host':'localhost',     # The host IP address or localhost.
    'port':'5432',          # The port to connect on.
    'sslmode':QgsDataSourceUri.SslDisable, # SslAllow, SslPrefer, SslRequire, SslVerifyCa, SslVerifyFull
    # user and password are not needed if stored in the authcfg or service
    'authcfg':'QconfigId',  # The QGIS athentication database ID holding connection details.
    'service': None,         # The PostgreSQL service to be used for connection to the database.
    'username':None,        # The PostgreSQL user name.
    'password':None,        # The PostgreSQL password for the user.
    # table and raster column details
    'schema':'public',      # The database schema that the table is located in.
    'table':'my_rasters',   # The database table to be loaded.
    'geometrycolumn':'rast',# raster column in PostGIS table
    'sql':None,             # An SQL WHERE clause. It should be placed at the end of the string.
    'key':None,             # A key column from the table.
    'srid':None,            # A string designating the SRID of the coordinate reference system.
    'estimatedmetadata':'False', # A boolean value telling if the metadata is estimated.
    'type':None,            # A WKT string designating the WKB Type.
    'selectatid':None,      # Set to True to disable selection by feature ID.
    'options':None,         # other PostgreSQL connection options not in this list.
    'enableTime': None,
    'temporalDefaultTime': None,
    'temporalFieldIndex': None,
    'mode':'2',             # GDAL 'mode' parameter, 2 unions raster tiles, 1 adds tiles separately (may require user input)
}
# remove any NULL parameters
uri_config = {key:val for key, val in uri_config.items() if val is not None}
# get the metadata for the raster provider and configure the URI
md = QgsProviderRegistry.instance().providerMetadata('postgresraster')
uri = QgsDataSourceUri(md.encodeUri(uri_config))

# the raster can then be loaded into the project
rlayer = iface.addRasterLayer(uri.uri(False), "raster layer name", "postgresraster")

Les couches raster peuvent également être créées à partir d’un service WCS.

layer_name = 'nurc:mosaic'
uri = "https://demo.geo-solutions.it/geoserver/ows?identifier={}".format(layer_name)
rlayer = QgsRasterLayer(uri, 'my wcs layer', 'wcs')

Voici une description des paramètres que l’URI du WCS peut contenir :

L’URI du WCS est composé de paires clé=valeur séparées par « & ». C’est le même format que la chaîne de requête dans l’URL, encodée de la même manière QgsDataSourceUri doit être utilisé pour construire l’URI afin de s’assurer que les caractères spéciaux sont encodés correctement.

  • url (obligatoire) : URL du serveur WCS. Ne pas utiliser VERSION dans l’URL, car chaque version de WCS utilise un nom de paramètre différent pour la version GetCapabilities, voir la version param.

  • identifier (obligatoire) : Nom de la couverture

  • time (facultatif) : position temporelle ou période de temps (beginPosition/endPosition [/timeResolution])

  • format (facultatif) : Nom du format supporté. La valeur par défaut est le premier format supporté avec tif dans le nom ou le premier format supporté.

  • crs (facultatif) : CRS sous la forme AUTHORITY:ID, par exemple EPSG:4326. La valeur par défaut est EPSG:4326 si elle est prise en charge ou le premier CRS pris en charge.

  • username (facultatif) : Nom d’utilisateur pour l’authentification de base.

  • password (facultatif) : Mot de passe pour l’authentification de base.

  • IgnoreGetMapUrl (facultatif, hack) : Si spécifié (défini à 1), ignorer l’URL de GetCoverage annoncée par GetCapabilities. Peut être nécessaire si un serveur n’est pas configuré correctement.

  • InvertAxisOrientation (optionnel, hack) : Si spécifié (défini à 1), changer d’axe dans la demande GetCoverage. Peut être nécessaire pour les CRS géographiques si un serveur utilise un mauvais ordre d’axes.

  • IgnoreAxisOrientation (optionnel, hack) : Si spécifié (défini à 1), n’inversez pas l’orientation des axes selon la norme WCS pour les CRS géographiques.

  • cache (facultatif) : contrôle de la charge du cache, comme décrit dans QNetworkRequest::CacheLoadControl, mais la requête est renvoyée en tant que PreferCache si elle a échoué avec AlwaysCache. Valeurs autorisées : AlwaysCache, PreferCache, PreferNetwork, AlwaysNetwork. La valeur par défaut est AlwaysCache.

Vous pouvez aussi charger une couche raster à partir d’un serveur WMS. Il n’est cependant pas encore possible d’avoir accès à la réponse de GetCapabilities à partir de l’API — vous devez connaître les couches que vous voulez :

urlWithParams = "crs=EPSG:4326&format=image/png&layers=tasmania&styles&url=https://demo.geo-solutions.it/geoserver/ows"
rlayer = QgsRasterLayer(urlWithParams, 'some layer name', 'wms')
if not rlayer.isValid():
  print("Layer failed to load!")

3.3. QgsProject instance

Si vous souhaitez utiliser les couches ouvertes pour le rendu, n’oubliez pas de les ajouter à l’instance QgsProject. L’instance QgsProject prend la propriété des couches et celles-ci peuvent être accessibles ultérieurement depuis n’importe quelle partie de l’application par leur identifiant unique. Lorsque la couche est retirée du projet, elle est également supprimée. Les couches peuvent être supprimées par l’utilisateur dans l’interface QGIS, ou via Python en utilisant la méthode removeMapLayer().

L’ajout d’une couche au projet actuel se fait à l’aide de la méthode addMapLayer() :

QgsProject.instance().addMapLayer(rlayer)

Pour ajouter une couche à une position absolue :

1
2
3
4
5
6
# first add the layer without showing it
QgsProject.instance().addMapLayer(rlayer, False)
# obtain the layer tree of the top-level group in the project
layerTree = iface.layerTreeCanvasBridge().rootGroup()
# the position is a number starting from 0, with -1 an alias for the end
layerTree.insertChildNode(-1, QgsLayerTreeLayer(rlayer))

Si vous voulez supprimer la couche, utilisez la méthode removeMapLayer() :

# QgsProject.instance().removeMapLayer(layer_id)
QgsProject.instance().removeMapLayer(rlayer.id())

Dans le code ci-dessus, l’identifiant de la couche est passé (vous pouvez l’obtenir en appelant la méthode id() de la couche), mais vous pouvez aussi passer l’objet de la couche lui-même.

Pour obtenir une liste des couches chargées et de leurs identifiants, utilisez la méthode mapLayers() :

QgsProject.instance().mapLayers()