1

I am trying to import shapefile data (polygons with all of the user fields) to postgis using osgeo. My code fails when shapefile contains both POLYGON and MULTIPOLYGON data.

from osgeo import ogr, osr


# Open shapefile
ogr_sf = ogr.Open('shapefiles/tst_2.shp')
shapefile_layer = ogr_sf.GetLayer(0)

# Open database connection
ogr_db = ogr.Open("PG:dbname='geo_development'"
                  "host='postgres' port='5432'"
                  "user='user'"
                  "password='password'")

db_layer = ogr_db.CopyLayer(shapefile_layer, 'tst_table['OVERWRITE=YES'])

I've got the next error message:

Warning 1: Geometry to be inserted is of type Multi Polygon, whereas the layer geometry type is Polygon. Insertion is likely to fail ERROR 1: COPY statement failed. ERROR: Geometry type (MultiPolygon) does not match column type (Polygon) CONTEXT: COPY tst_table, line 2, column wkb_geometry: "0106000020E6100000020000000103000000010000000700000083F9A3C6597B5EC0ACADB807A7AE424040B2E29AEC7A5EC0..."

I've tried to walk around defining the postgis table first and then copy data:

from osgeo import ogr, osr

ogr_sf = ogr.Open('shapefiles/tst_2.shp')
shapefile_layer = ogr_sf.GetLayer(0)
layer_definition = shapefile_layer.GetLayerDefn()

ogr_db = ogr.Open("PG:dbname='geo_development'"
                  "host='postgres' port='5432'"
                  "user='user'"
                  "password='password'")

# Define spatial reference system
srs = osr.SpatialReference()
srs.ImportFromEPSG(4326)

# Create layer
db_layer = ogr_db.CreateLayer('tst_table', srs,
                              ogr.wkbMultiPolygon, ['OVERWRITE=YES'])
for i in range(layer_definition.GetFieldCount()):
    db_layer.CreateField(layer_definition.GetFieldDefn(i))

# Copy features
for feature in shapefile_layer:
    db_layer.CreateFeature(feature)

This time the error msg is opposite to the previous one:

Warning 1: Geometry to be inserted is of type Polygon, whereas the layer geometry type is Multi Polygon. Insertion is likely to fail ERROR 1: COPY statement failed. ERROR: Geometry type (Polygon) does not match column type (MultiPolygon) CONTEXT: COPY tst_table, line 1, column wkb_geometry: "0103000020E6100000010000000C000000116AC8BB107B5EC043A499E388B04240D980B833AC7A5EC07653090DC6B04240D8..."

Does anyone know how to overcome this?

  • 2
    You must cast all geometries into multipolygons. With ogr2ogr you use the -nlt value "multipolygon" or "promote_to_multi". Find out how to do the same with python. – user30184 Apr 27 '18 at 15:46
1

Thank you @user30184, your answer was helpful. I explicitly cast feature's geometry to multipolygon if it's type is a polygon.

Link to the docs: Force polygon to multipolygon

from osgeo import ogr, osr


def get_gdal_connection_string():
    return ("PG:dbname='geo_development'"
            "host='postgres' port='5432'"
            "user='user'"
            "password='password'")


def create_layer_from_definition(ogr_db, layer_definition, srid=4326):
    srs = osr.SpatialReference()
    srs.ImportFromEPSG(srid)
    db_layer = ogr_db.CreateLayer('tst_table', srs,
                                  ogr.wkbMultiPolygon,
                                  ['OVERWRITE=YES'])
    for i in range(layer_definition.GetFieldCount()):
        db_layer.CreateField(layer_definition.GetFieldDefn(i))
    return db_layer


def copy_features(src_layer, dest_layer):
    for feature in src_layer:
        geom = feature.GetGeometryRef()
        if geom.GetGeometryType() == ogr.wkbPolygon:
            feature.SetGeometryDirectly(ogr.ForceToMultiPolygon(geom))
        dest_layer.CreateFeature(feature)


if __name__ == '__main__':
    # Create ogr object from shapefile
    ogr_sf = ogr.Open('shapefiles/tst.shp')
    shapefile_layer = ogr_sf.GetLayer(0)
    layer_definition = shapefile_layer.GetLayerDefn()

    # Create ogr object for postgis
    conn_str = get_gdal_connection_string()
    ogr_db = ogr.Open(conn_str)


    db_layer = create_layer_from_definition(
        ogr_db,
        layer_definition)

    copy_features(shapefile_layer, db_layer)

This worked for me for about 7.5 times faster than shp2pgsql on a large dataset.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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