PyQGIS – Getting Layer by Name in PyQGIS

layer-namelayerspyqgisqgis-plugins

I have a plugin which finds buffer for list of cities, provided the distance. The state and city names are taken from the attribute table and gets filtered accordingly. What I want is my plugin should identify the layer name or order of the layer in canvas, irrespective of other layers present in the canvas and access the corresponding attributes from that layer.

I am also just curious whether pointing a specific layer name in code would cause any error in iteration though some other layers are present?

Below is my code please tell me where should I make changes and what would be the change?

if dist and centerCity:
    #QMessageBox.information(self.dlg, "info", "both True")
    st = '"name" = \'' + centerCity + '\''
    exp = QgsExpression(st)
else:
    QMessageBox.warning(self.dlg, "Enter the distance","Enter the distance and try again.")        
    return          #terminate the function

layer = self.iface.activeLayer() 
it = layer.getFeatures(QgsFeatureRequest(exp))
feature = it.next()
mbuf = feature.geometry().buffer(dist, 2)       

iterFeat = layer.getFeatures()

for f in iterFeat:
    geom2 = f.geometry()
    valTest = QgsGeometry.within(geom2, mbuf) 

Best Answer

UPDATE: 10.04.2018

Using QGIS 3.x you can use the mapLayersByName method from QgsProject class in this way:

layers = QgsProject.instance().mapLayersByName('my layer name')

Since you can have several layers in QGIS with the same name in the layers panel, the method above gives you a list of matching layers.

Before accessing any element in the layer list, you should check if the list has elements. If so you can access, for instance, its first element (layer) in this way:

if layers: 
    layer = layers[0]

Which would be the common case of having a single layer matching the name you searched for.


For QGIS 2.x:

You would just need to make sure your layer has a name you can distinguish from others. Instead of layer = self.iface.activeLayer(), do:

layer=None
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
    if lyr.name() == "YOUR_LAYER_NAME":
        layer = lyr
        break

If you don't trust the layer name (after all, it can be changed by the user at any time), you could try to check the layer source. If your layer is a Shapefile, you could check the path to the Shapefile, this way:

layer=None
for lyr in QgsMapLayerRegistry.instance().mapLayers().values():
    if lyr.source() == "/path/to/shapefile.shp":
        layer = lyr
        break

EDIT: As @Jakob has pointed out in comments, you can write the first block in one line:

layerList = QgsMapLayerRegistry.instance().mapLayersByName("YOUR_LAYER_NAME")

Or:

layerList = [lyr for lyr in QgsMapLayerRegistry.instance().mapLayers().values() if lyr.name() == "YOUR_LAYER_NAME"]

Anyway, you would need to check that layerList is not empty before accessing its first element:

if layerList: 
    layer = layerList[0]
Related Question