2

I'm trying to automate the process of exporting around 20 shapefiles from my QGIS project into a single GeoPackage using PyQGIS. Here is the code:

import os 
from qgis.core import (
QgsProject,
QgsVectorFileWriter,
QgsCoordinateTransformContext,
QgsVectorLayer
)
output_gpkg = "C:/Users/kk/Desktop/QGIS/PyQGIS/CODES/output.gpkg"

if os.path.exists(output_gpkg):
os.remove(output_gpkg)

transform_context = QgsCoordinateTransformContext()

options = QgsVectorFileWriter.SaveVectorOptions()
options.driverName = "GPKG"
options.fileEncoding = "UTF-8"

for layer in QgsProject.instance().mapLayers().values():
if isinstance(layer, QgsVectorLayer) and layer.source().lower().endswith(".shp"):
    options = QgsVectorFileWriter.SaveVectorOptions()
    options.driverName = "GPKG"
    options.fileEncoding = "UTF-8"
    options.layerName = layer.name()
    options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
    error = QgsVectorFileWriter.writeAsVectorFormatV3(
        layer,
        output_gpkg,
        transform_context,
        options
    )

    if error[0] == QgsVectorFileWriter.NoError:
        print(f"Successfully exported '{layer.name()}' to GeoPackage!")
    else:
        print(f"Export failed for '{layer.name()}': {error[1]}")

Although the code works sometimes, I keep getting this error:

Opening of data source in update mode failed (OGR error)

1 Answer 1

3

See the following discussion for context: https://github.com/qgis/QGIS/issues/55398. Setting the actionOnExistingFile attribute of QgsVectorFileWriter.SaveVectorOptions to QgsVectorFileWriter.CreateOrOverwriteLayer when the file does not yet exist results in the error you describe.

I also encountered this recently and the solution I implemented, which I suggest to you is to add a check inside your loop to determine if the file exists or not, and conditionally set the actionOnExistingFile attribute to QgsVectorFileWriter.CreateOrOverwriteLayer only if the output geopackage exists. Otherwise, allow the actionOnExistingFile attribute to fall back to the default QgsVectorFileWriter.CreateOrOverwriteFile. E.g.

...
for layer in QgsProject.instance().mapLayers().values():

    if isinstance(layer, QgsVectorLayer) and layer.source().lower().endswith(".shp"):
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = "GPKG"
        options.fileEncoding = "UTF-8"
        options.layerName = layer.name()

        if os.path.exists(output_gpkg):
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
...

You should also remove the instance of QgsVectorFileWriter.SaveVectorOptions declared outside the loop, since you are creating a new instance on each iteration.

I would also suggest retrieving the transform context from the project e.g. transform_context = QgsProject.instance().transformContext().

Final cleaned up code would look something like:

import os
from qgis.core import (
    QgsProject,
    QgsVectorFileWriter,
    QgsVectorLayer,
)


output_gpkg = "C:/Users/kk/Desktop/QGIS/PyQGIS/CODES/output.gpkg"


if os.path.exists(output_gpkg):
    os.remove(output_gpkg)


transform_context = QgsProject.instance().transformContext()

for layer in QgsProject.instance().mapLayers().values():

    if isinstance(layer, QgsVectorLayer) and layer.source().lower().endswith(".shp"):
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = "GPKG"
        options.fileEncoding = "UTF-8"
        options.layerName = layer.name()

        if os.path.exists(output_gpkg):
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer

        error = QgsVectorFileWriter.writeAsVectorFormatV3(
            layer,
            output_gpkg,
            transform_context,
            options
        )

        if error[0] == QgsVectorFileWriter.NoError:
            print(f"Successfully exported '{layer.name()}' to GeoPackage!")
        else:
            print(f"Export failed for '{layer.name()}': {error[1]}")

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.