QGIS – Adding VRT via PyQGIS When GUI Load Works

gdalpyqgisqgisqgis-3vrt

How to reproduce my issue? Create the 2 files, a CSV and a VRT from below recipe (also available at https://gist.github.com/ThomasG77/56db21b335e25668ff86c2e8359bf3d1).

Then, try to add them with both GUI and PyQGIS.

Tested on QGIS 3.16 on my side on an Ubuntu 18.04

My exemple-valide.csv CSV content

id;longitude;latitude;famille_arbre;genre_arbre;espece_arbre;cultivar_variete_arbre;nom_vernaculaire;code_insee;code_postal;adresse;matricule_arbre;date_plantation;hauteur;diametre;type_sol;type_enracinement;port_arbre;arbre_remarquable;arbre_protege;contraintes_sol;contrainte_aeriennes;eclairage;arrosage;allergie;remarque
1;49.802;0.3768;Sapindaceae;Acer;campestre;;Erable champetre;13028;13600;320 Avenue Joseph Roumanille;259001;2018-05-12;100;58;Argilo-sableux;Oblique;Boule;Non;Non;Sol perméabilisé;Cables éléctriques;Oui;Goutte à goutte;3;
2;43.2959;5.3761;Rosaceae;Pyrus;calleryana;chanticleerc;"Poirier ""chanticleerc""";13055;13001;60 rue sainte;1998PyrCal130011150;1998-04-20;235;73;Argileux;Pivotant;;Non;Non;Grille abimée;proximité d'un mur;Non;;;tronc abimé lors de travaux
3;43.2915;5.4805;Platanaceae;Platanus;occidentalis;;Platane d'Amérique;13055;13002;72 Boulevard des Dames;;1990-03-01;;;;;;Non;Non;;;Oui;;2;dans un alignement
4;44.2920;5.3705;Pinaceae;Pinus;sylvestris;;Pin sylvestre;13055;13013;48 rue des hauts bois;;;;;Sableux;Pivotant;Cône;Oui;Non;;;;;;

My exemple-valide.vrt file

<OGRVRTDataSource>
  <OGRVRTLayer name="exemple-valide">
    <SrcDataSource relativeToVRT="1" shared="1">exemple-valide.csv</SrcDataSource>
    <SrcLayer>exemple-valide</SrcLayer>
    <GeometryType>wkbPoint</GeometryType>
    <LayerSRS>WGS84</LayerSRS>
    <GeometryField encoding="PointFromColumns" x="longitude" y="latitude"/>
    <Field name="id" type="Integer" src="id"/>
    <Field name="longitude" type="Real" src="longitude"/>
    <Field name="latitude" type="Real" src="latitude"/>
    <Field name="famille_arbre" type="String" src="famille_arbre"/>
    <Field name="genre_arbre" type="String" src="genre_arbre"/>
    <Field name="espece_arbre" type="String" src="espece_arbre"/>
    <Field name="cultivar_variete_arbre" type="String" src="cultivar_variete_arbre"/>
    <Field name="nom_vernaculaire" type="String" src="nom_vernaculaire"/>
    <Field name="code_insee" type="String" src="code_insee"/>
    <Field name="code_postal" type="String" src="code_postal"/>
    <Field name="adresse" type="String" src="adresse"/>
    <Field name="matricule_arbre" type="String" src="matricule_arbre"/>
    <Field name="date_plantation" type="Date" src="date_plantation"/>
    <Field name="hauteur" type="Real" src="hauteur"/>
    <Field name="diametre" type="Real" src="diametre"/>
    <Field name="type_sol" type="String" src="type_sol"/>
    <Field name="type_enracinement" type="String" src="type_enracinement"/>
    <Field name="port_arbre" type="String" src="port_arbre"/>
    <Field name="arbre_remarquable" type="String" src="arbre_remarquable"/>
    <Field name="arbre_protege" type="String" src="arbre_protege"/>
    <Field name="contraintes_sol" type="String" src="contraintes_sol"/>
    <Field name="contrainte_aeriennes" type="String" src="contrainte_aeriennes"/>
    <Field name="eclairage" type="String" src="eclairage"/>
    <Field name="arrosage" type="String" src="arrosage"/>
    <Field name="allergie" type="Integer" src="allergie"/>
    <Field name="remarque" type="String" src="remarque"/>
  </OGRVRTLayer>
</OGRVRTDataSource>

Both VRT and CSV files are in the same directory

When I load the VRT manually via the GUI, it displays correctly whereas I do it using the following, it does not

vrt_dest_path = 'myabsolutepath_to_exemple-valide.vrt'
uri_vrt = f"{vrt_dest_path}|layername='exemple-valide'"
vectorLayer = QgsVectorLayer(uri_vrt, layername, "ogr")
project.addMapLayer(vectorLayer)

What do I miss that make things failed with PyQGIS? Something obvious?

I've made some assumptions/deductions below but without findind out where is my issue…

From what I see, it seems related to QGIS through the GUI detecting the block content

    <GeometryType>wkbPoint</GeometryType>
    <LayerSRS>WGS84</LayerSRS>
    <GeometryField encoding="PointFromColumns" x="longitude" y="latitude"/>

whereas within PyQGIS it does not. I suppose this also because of differences between QGIS file qgs content part for both <maplayer> blocks e.g

XML excerpt from qgs file when added via GUI https://gist.github.com/ThomasG77/56db21b335e25668ff86c2e8359bf3d1#file-maplayer_gui-xml

vs

XML excerpt from qgs file when added via PyQGIS where you can notice a geometry="Unknown geometry" https://gist.github.com/ThomasG77/56db21b335e25668ff86c2e8359bf3d1#file-maplayer_pyqgis-xml

Best Answer

I could get the same error "Unavailable layer!" as you on my QGIS 3.18.2-Zürich.

error

Unfortunatelly, until now I can not find out the reason for your problem.

However, I can offer several solutions.

You can try this:

from qgis.core import *

vrt_path = "D:/TESTING/exemple-valide.vrt"
vrt_info = QFileInfo(vrt_path)
vrt_name = vrt_info.baseName()

vrt_layer = QgsVectorLayer(vrt_path, vrt_name, "ogr")

if not vrt_layer.isValid():
    print (f'{vrt_layer} is not valid!')
    
QgsProject.instance().addMapLayer(vrt_layer)

As an alternative, there is "Create points layer from table" algorithm available under "qgis:createpointslayerfromtable" in PyQGIS

import processing

vrt_dest_path = "D:/TESTING/exemple-valide.vrt"

processing.runAndLoadResults("qgis:createpointslayerfromtable",
    {'INPUT' : vrt_dest_path,
    'MFIELD' : '', 
    'OUTPUT' : 'TEMPORARY_OUTPUT',
    'TARGET_CRS' : QgsCoordinateReferenceSystem('EPSG:4326'),
    'XFIELD' : 'longitude',
    'YFIELD' : 'latitude',
    'ZFIELD' : ''})

Both pieces of code end up in:

reuslt

Related Question