4

I have 3 layers in one geopackage, all with the same name but different geometry: Point, Line, Polygon (originally coming from a MapInfo .TAB, which supports multi-geometry in one file). I already have loaded them in my project. Now i want to run native:centroids over the polygon-layer to get the centroids and save the result back into the Geopackage (and overwrite the existing point layer + delete if possible the line and polygon layer).

My script so far:


from qgis.utils import iface
from qgis.core import *
import os 

layers = qgis.core.QgsProject.instance().layerTreeRoot().layerOrder()

for lyr in layers:
    if lyr.type() == 0 and lyr.name() == 'lightPosts':
        basename = lyr.name()
        geom = lyr.wkbType()
        layer_path = lyr.source()
        layer_path = layer_path.replace("Polygon","Point")
          
        input_layer = 'lightPosts'
        if geom == 3:
            params = {'ALL_PARTS' : False, 'INPUT' : input_layer, 'OUTPUT' : layer_path}
            processing.runAndLoadResults("native:centroids",params)

Following error message it prints:

_core.QgsProcessingException: Could not create layer H:/Test_Data.gpkg|layername=lightPosts|geometrytype=Point.gpkg: Creation of data source failed (OGR error: sqlite3_open(H:/Test_Data.gpkg|layername=lightPosts|geometrytype=Point.gpkg) failed: unable to open database file)

It seems it can not acces or overwrite the layer already contained in the geopackage. How can i circumvent this problem?

2
  • 2
    I think the problem here is that you have gpkg file is open in QGIS and trying to editing. That you cannot do as far as I experienced. If the gpkg is not open, you can surely overwrite it.
    – Nil
    Commented Apr 29, 2021 at 13:35
  • the layer i want to overwrite is not in edit mode, nor any other layer. If i run Centroids with GUI, it overwrites the layer without problem
    – sn1ks
    Commented May 3, 2021 at 5:58

1 Answer 1

2

You can load the result of "native:centroids" into memory and then manipulate your .gpkg file. This has the advantage that you can also build in some checks before you overwrite your original source file. Something like this:

# load layers from file
source_path = os.path.join(<YOUR GEOPACKAGE PATH>) + "|layername=<POLYGON LAYER>"
source_layer = QgsVectorLayer(source_path, "Polygons", "ogr")
target_path = os.path.join(<YOUR GEOPACKAGE PATH>) + "|layername=<POINT LAYER>"
target_layer = QgsVectorLayer(target_path, "Points", "ogr")

# process layers
params = {'ALL_PARTS' : False, 'INPUT' : source_layer, 'OUTPUT' : 'memory:'}
centroids = processing.run("native:centroids",params)['OUTPUT']

# Here you can add some checks for your result layer

# Write results to file
with edit(target_layer):
    for feature in target_layer.getFeatures():
        target_layer.deleteFeature(feature.id())
    for feature in centroids.getFeatures():
        target_layer.addFeature(feature)

# Optionally add the result layer to your layer tree
QgsProject.instance().addMapLayer(target_layer)

Note that I loaded the layers directly from the file, whitout going through the iface. For me this is more straight forward and spares me the code to pick out the right one from the layer tree. Using iface should work as well, though.

Variation: If you don't want to replace the old points but want to add the centroids to the point layer, you can use the hint from Adding feature to geopackage layer and regenerating primary key using PyQGIS? and manipulate your geopackage like this:

# Write results to file
with edit(target_layer):
    idx = target_layer.fields().indexFromName("fid")
    for feature in centroids.getFeatures():
        if idx is not None:
            feature[idx] = None
        target_layer.addFeature(feature)
2
  • well, this looks promising. now target_layer.addFeature(feature) is causing problems: Provider errors:', ' OGR error creating feature -10281: failed to execute insert : UNIQUE constraint failed: <Layername>.fid' Any idea why it will not create new (or overwrite the old) FID?
    – sn1ks
    Commented May 4, 2021 at 9:56
  • 1
    That happens if you haven't properly deleted all features from the original layer. As the error sais, feature ids have to be unique and geopackage doesn't let you overwrite features. So either you want to replace the original points with your centroids. In that case check if you have implemented the code that deletes the old points correctly. Or, if you actually want to keep your old points in the layer, this will help you: gis.stackexchange.com/questions/336256/…
    – lueho
    Commented May 4, 2021 at 10:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.