3

I'm writing a plugin that needs to check a few things for every shapefile layer in the current project. I am iterating over the layers as shown below, but cant figure out how to check if it is a shapefile. I don't consider using the URI to be a reliable method.

for layer in QgsProject.instance().mapLayers().values():
    dp = layer.dataProvider()
    uri = dp.dataSourceUri()
    if dp.storageFormat() == 'shapefile': # not valid code
        print(dp) 
        #verify stuff

1 Answer 1

6

The shapefile format is a geospatial Vector data format, therefore on a first stage I suggest to catch all of vector layers with the QgsVectorLayer class.

There are several approaches to achieve it with:

  • the isinstance() function:

    isinstance(layer, QgsVectorLayer)
    
  • the .type() method from the QgsMapLayer class:

    layer.type() == QgsMapLayer.VectorLayer
    
  • the .name() method from the QgsDataProvider class:

    layer.dataProvider().name() == 'ogr'
    

    Here is a list of all ogr drivers:

    ['ARCGEN', 'AVCBin', 'AVCE00', 'AmigoCloud', 'BAG', 'CAD', 'CSV', 'CSW', 'Carto', 'Cloudant', 'CouchDB', 'DB2ODBC', 'DGN', 'DXF', 'EDIGEO', 'EEDA', 'ESRI Shapefile', 'ESRIC', 'ESRIJSON', 'Elasticsearch', 'FlatGeobuf', 'GML', 'GMLAS', 'GPKG', 'GPSBabel', 'GPSTrackMaker', 'GPX', 'GeoJSON', 'GeoJSONSeq', 'GeoRSS', 'Geoconcept', 'Geomedia', 'HTTP', 'Idrisi', 'Interlis 1', 'Interlis 2', 'JML', 'JP2ECW', 'JP2OpenJPEG', 'KML', 'LIBKML', 'LVBAG', 'MBTiles', 'MSSQLSpatial', 'MVT', 'MapInfo File', 'MapML', 'Memory', 'MySQL', 'NAS', 'NGW', 'OAPIF', 'OCI', 'ODBC', 'ODS', 'OGCAPI', 'OGR_GMT', 'OGR_OGDI', 'OGR_PDS', 'OGR_SDTS', 'OGR_VRT', 'OSM', 'OpenFileGDB', 'PCIDSK', 'PDF', 'PDS4', 'PGDUMP', 'PGeo', 'PLSCENES', 'PostgreSQL', 'REC', 'S57', 'SOSI', 'SQLite', 'SVG', 'SXF', 'Selafin', 'TIGER', 'TopoJSON', 'UK .NTF', 'VDV', 'VFK', 'VICAR', 'WAsP', 'WFS', 'Walk', 'XLS', 'XLSX', 'netCDF']

    More information can be found under Python GDAL/OGR Cookbook 1.0 documentation | Vector Layers.

After that all the vector layers will be available:

for layer in QgsProject.instance().mapLayers().values():
    if isinstance(layer, QgsVectorLayer):
        print(layer)

However, at this point there should be considered a second stage to distinct between types of the vector layer: shapefile, GeoPackage, GeoJSON etc. There are several ideas, that use:

  • the .storageType() function:

     for layer in QgsProject.instance().mapLayers().values():
         if isinstance(layer, QgsVectorLayer):
             if layer.storageType() == 'ESRI Shapefile':
                 print(layer)
    
  • the .dataProvider().dataSourceUri() methods combination:

     for layer in QgsProject.instance().mapLayers().values():
         if isinstance(layer, QgsVectorLayer):
             if '.shp' in layer.dataProvider().dataSourceUri():
                 print(layer)
    
  • the os.path.split() function from the os.path module:

     from os.path import split
    
     for layer in QgsProject.instance().mapLayers().values():
         if isinstance(layer, QgsVectorLayer):
             dir_name, file_name = os.path.split(layer.dataProvider().dataSourceUri())
             if '.shp' in file_name:
                 print(layer)
    
  • the os.path.splitext() function from the os.path module:

     from os.path import splitext
    
     for layer in QgsProject.instance().mapLayers().values():
         if isinstance(layer, QgsVectorLayer):
             file_name, file_extension = splitext(layer.dataProvider().dataSourceUri())
             if '.shp' in file_extension:
                 print(layer)
    

As an alternative one can use:

  • the .source() method from the QgsMapLayer class

     for layer in QgsProject.instance().mapLayers().values():
         if '.shp' in layer.source():
             print(layer)
    

References:

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.