9

I have an issue using PyQGIS to save a memory layer to a GeoPackage that does not already exist. This is equivalent to using the Make permanent... option in the Layers context menu, to save to a new GeoPackage.

I have a couple of similar PyQGIS methods for making memory layers permanent. However, both of these only work when the GeoPackage already exists. This is problematic for the first layer that needs to be saved.

This is one method I have been using:

pathToGpkg = 'E:/path/to/geopackage.gpkg'
layer = iface.activeLayer()
processing.run("gdal:convertformat", { 'INPUT' : layer, 'OPTIONS' : '-update -nln '+layer.name(), 'OUTPUT' : pathToGpkg })
layer.setDataSource(pathToGpkg + f'|layername={layer.name()}', layer.name(), 'ogr')

Alternatively this one based on: https://gis.stackexchange.com/a/455474/129409

# reference to memory layer
layer = iface.activeLayer()

# save location
geopackage = 'E:/path/to/geopackage.gpkg'

# write the layer to disk
options = QgsVectorFileWriter.SaveVectorOptions()
options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer 
options.layerName = layer.name()
_writer = QgsVectorFileWriter.writeAsVectorFormatV3(layer, geopackage, QgsCoordinateTransformContext(), options) 

# change the data source
layer.setDataSource(geopackage + f'|layername={layer.name()}', layer.name(), 'ogr')

Both throw errors when the GeoPackage doesn't exist.

Is there a way of using PyQGIS for either:

  • saving to a GeoPackage without the GeoPackage already existing, or
  • initialising an empty GeoPackage (my reading is that a GeoPackage needs a layer, but my understanding may be wrong!)
1
  • It's great that the answers all solve the problem simply and succinctly - I've accepted the one that I used, but they could all be useful depending on the situation. Commented Nov 26, 2023 at 5:37

3 Answers 3

10

You can use the following lines in your PyQGIS script to make an empty GeoPackage.

from osgeo import ogr

gpkg_path = "c:/test/test.gpkg"
ds = ogr.GetDriverByName('GPKG').CreateDataSource(gpkg_path)

If you are not going to use it in your script later, you can skip the leading ds =.

6

Just to round out the list of alternatives, the first script can be made to work for a new file by changing the option for gdal:convertformat (wrapper for ogr2ogr) from -update to -overwrite - probably analogous to CreateOrOverwriteLayer vs CreateOrOverwriteFile.

pathToGpkg = 'E:/path/to/geopackage.gpkg'
layer = iface.activeLayer()
processing.run("gdal:convertformat", { 'INPUT' : layer, 'OPTIONS' : '-overwrite -nln '+layer.name(), 'OUTPUT' : pathToGpkg })
layer.setDataSource(pathToGpkg + f'|layername={layer.name()}', layer.name(), 'ogr')
5

The second script works if you change the flag to the correct one which is QgsVectorFileWriter.CreateOrOverwriteFile:

# reference to memory layer
layer = iface.activeLayer()

# save location
geopackage = 'E:/path/to/geopackage.gpkg'

# write the layer to disk
options = QgsVectorFileWriter.SaveVectorOptions()
options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
options.layerName = layer.name()
_writer = QgsVectorFileWriter.writeAsVectorFormatV3(layer, geopackage, QgsCoordinateTransformContext(), options) 

# change the data source
layer.setDataSource(geopackage + f'|layername={layer.name()}', layer.name(), 'ogr')

QgsVectorFileWriter.SaveVectorOptions.actionOnExistingFile behavior with CreateOrOverwriteLayer doesn't work when the file doesn't exist or it isn't a geopackage.

Which is quite misleading since the variable is called "actionOnExistingFile" but it changes the behavior also for non-existing file (which might be an actual bug, but I couldn't find any issues relating to it on github issues.

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.