6

I have been working on putting together a simple script that converts a file geodatabase to a GeoPackage. I have a GeoPackage with empty tables set up so that the data in the gdb can be appended easily. I have tried different approaches and want to keep the code simple. I cannot for the life of me figure out how to make this work though.

Does anyone have any thoughts about what I am doing wrong? Basically, I am trying to iterate through every featureclass in a GDB and export it/append it to a gpkg.

outputGpkg = r"D:\export.gpkg"
inputGdb = r"D:\import.gdb"
fileEncoding = "UTF-8"

gdbFcs = [ "Feature1", "Feature2", "FeatureN" ] # eventually I want to find a routine to pull fc names from gdb and populate the array

for fc in gdbFcs:
    gdbLyr = QgsVectorLayer(inputGdb + "|layername=" + fc, fc, "ogr")
    print(gdbLyr)
    #if gdbLyr.type() == QgsMapLayer.VectorLayer:
    #    _writer = QgsVectorFileWriter.writeAsVectorFormat(gdbLyr, outputGpkg, fileEncoding, gdbLyr.crs())
    _writer = QgsVectorFileWriter.writeAsVectorFormat(gdbLyr, outputGpkg, fileEncoding, gdbLyr.crs())

2 Answers 2

6

This seems to be working:

from osgeo import ogr

fgdb = r"C:\GIS\data\somefilegeodatabase.gdb"
outdb = r"C:\GIS\data\testdata\OK.gpkg" #Has to be created in advance
fileEncoding = "UTF-8"

driver = ogr.GetDriverByName("OpenFileGDB")
data = driver.Open(fgdb, 0)

#List all layers in the file geodatabase
feature_class_list = []
for i in data:
    foo = i.GetName()
    feature_class_list.append(foo)
    
#Write to geopackage
for fc in feature_class_list:
    gdbLyr = QgsVectorLayer("{0}|layername={1}".format(fgdb, fc), fc, "ogr")
    print('Writing: ', fc)
    options = QgsVectorFileWriter.SaveVectorOptions()
    options.driverName = "GPKG"
    options.layerName = fc
    options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
    options.EditionCapability = 0 #CanAddNewLayer 
    QgsVectorFileWriter.writeAsVectorFormat(gdbLyr, outdb, options)
5

This code is very similar to what @BERA has posted. The difference is this python code runs in the interactive python console in QGIS (tested on version 3.16.3) to copy all vector layers from an ESRI file geodatabase to a GeoPackage. Interestingly, it also will copy vectors from within Feature Datasets contained in a geodatabase.

gdbPath = r"E:\ESRI_data.gdb"
gpkgPath = r"E:\My_GeoPackage.gpkg"
gdbLayer = QgsVectorLayer(gdbPath,"targ ESRI GeoDatabase","ogr")
subLayers = gdbLayer.dataProvider().subLayers()
for subLayer in subLayers:
    parts = subLayer.split('!!::!!')
    layerName = parts[1]
    geotype = parts[2]
    lpath = r"{}|layername={}".format(gdbPath,layerName)
    olayer = QgsVectorLayer(lpath, layerName, "ogr")
    # set options
    options = QgsVectorFileWriter.SaveVectorOptions()
    options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
    options.layerName = layerName
    _writer = QgsVectorFileWriter.writeAsVectorFormat(olayer, gpkgPath, options)
    if _writer:
        print(layerName, _writer)
4
  • 1
    That really works, it is needed to be published as a processing algorithm. Please contact me if you're fine with it, I can do it with your credits Commented Oct 5, 2021 at 19:09
  • I have an Esri geodatabase that I want to convert to a geopackage. The gdb file contains a geological map and thus has different geometries (point, polygon and polyline). But when I make a new empty geopackage I can only chose 1 geometry type. It is also unclear if I have to make the tables beforehand. And I agree that this deserves to be a processing algorithm.
    – Gin
    Commented Oct 15, 2021 at 13:32
  • Its fine with me if this code is adapted as a processing algorithm. It was cobbled together with minor changes from the PyQGIS Developer Cookbook.
    – Rob Irwin
    Commented Oct 20, 2021 at 18:22
  • @Gin - when you make a new geopackage in QGIS (vers 3x) , it always requires you to create a new vector - I usually just create a dummy vector, then delete it out of the new geopackage after its created.
    – Rob Irwin
    Commented Oct 20, 2021 at 18:23

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.