xsmet
xsmet

Reputation: 29

Creating a virtual QgsVectorLayer with PyQGIS outside of QGIS

In QGIS' built in python prompt, I can do this

>>> linesfile
'C:\\Users\\path\\to\\Lines.csv'
>>> mylayer = QgsVectorLayer(linesfile, "GPSLines", "ogr")
>>> mylayer.isValid()
True
>>> mylayer.featureCount()
6624

And successfully create a virtual layer that references the freshly created one:

>>> vlayer = QgsVectorLayer("?query=SELECT * FROM 'GPSLines'", 'myvlayer', 'virtual')
>>> vlayer.isValid()
True
>>> vlayer.featureCount()
6624

However, trying the same from an external editor (VSCode), it doesn't behave as expected. The created layer seems to be invalid, but I can't see why or even find an error message that explains more. It feels as if the 'GPSLines' layer that I just created disappears into thin air.

mylayer = QgsVectorLayer(linesfile, "GPSLines", "ogr")
mylayername = mylayer.name()
if not mylayer.isValid():
    print("Layer failed to load")
else:
    print("Layer loaded.")
    print("Original number of features: " + str(mylayer.featureCount()))
vlayer = QgsVectorLayer("?query=SELECT * FROM 'GPSLines'", 'myvlayer','virtual')
if not vlayer.isValid():
    error_msg = vlayer.lastError()
    print(f"Virtual layer creation failed with error: {error_msg}")
    print("Filtered Layer failed to load")
else:
    print("Filtered Layer loaded.")
    print("Filtered number of features: " + str(vlayer.featureCount()))

Output:

Layer loaded.
Original number of features: 6624
Virtual layer creation failed with error:
Filtered Layer failed to load

Any help or pointers welcome - I have no clue where to look further.

Upvotes: 1

Views: 95

Answers (1)

Zeros-N-Ones
Zeros-N-Ones

Reputation: 1082

The difference between QGIS Python console and your external script is the layer registry/management. In QGIS Python console, when you create a layer, it's automatically added to the project's layer registry but when running from an external script, you need to add the layer to the project for it to be available for virtual layer queries.

You should modify your script to handle this:

from qgis.core import QgsProject

# Create and add the source layer
mylayer = QgsVectorLayer(linesfile, "GPSLines", "ogr")
if not mylayer.isValid():
    print("Layer failed to load")
else:
    # Add layer to the project
    QgsProject.instance().addMapLayer(mylayer)
    print("Layer loaded.")
    print("Original number of features: " + str(mylayer.featureCount()))

# Now create the virtual layer
vlayer = QgsVectorLayer("?query=SELECT * FROM 'GPSLines'", 'myvlayer', 'virtual')
if not vlayer.isValid():
    error_msg = vlayer.lastError()
    print(f"Virtual layer creation failed with error: {error_msg}")
    print("Filtered Layer failed to load")
else:
    print("Filtered Layer loaded.")
    print("Filtered number of features: " + str(vlayer.featureCount()))

Virtual layers in QGIS need to reference layers that are part of the project. When you run this in QGIS Python console, the layer is automatically added to the project, which is why it works there. In an external script, we need to add it.

If you're running this completely standalone (not from within QGIS at all), you'll need to make sure you've initialized QGIS properly. You'd need something like this at the start of your script:

from qgis.core import QgsApplication

# Initialize QGIS Application
qgs = QgsApplication([], False)
qgs.initQgis()

# Your existing code here...

# Clean up when done
qgs.exitQgis()

Upvotes: 1

Related Questions