39

I'm having trouble figuring out how to iterate over map layers. I can access the currently highlighted layer in the table of contents via iface.activeLayer() but I want my code to operate on all layers.

I don't see anything in the API that provides easy access to this functionality and couldn't find a good online example but maybe I missed something?

2
  • I don't see how you guys are using QgsMapLayerRegistry or QgsProject. In QGIS 3.0.2 this does not work. However, iface.mapCanvas().layers() does. Well, kind of. It only seems to give you the active layers (the ones you have checked in the Layers pane). Does anyone know how to get a list of all Layers, even those unchecked in the Layers pane? Also, if using Plugin Builder, it creates the shell of your plugin for you. The run function has a "self" parameter, which is needed to use iface. i.e. self.iface.mapCanvas().layers(), just fyi.
    – ajpieri
    Oct 12, 2018 at 13:11
  • Please, do not forget about "What should I do when someone answers my question?"
    – Taras
    Mar 14, 2022 at 6:48

5 Answers 5

26

Try...

# substitute 'self' with 'qgis.utils.iface' when run from Python console
# 'self.iface = iface' would usually precede this command in your class 
layers = self.iface.legendInterface().layers()

for layer in layers:
    layerType = layer.type()
    if layerType == QgsMapLayer.VectorLayer:
        # do some stuff here

Culled from consolidatethread.py from QConsolidate plugin.

Description of QgsLegendInterface object returned from legendInterface().

Edit: added info on 'self' above.

3
  • Thanks! That did the trick. I guess I'm too used to the ESRI world where legend is the object in the map layout and table of contents refers to the list of layers. May 26, 2012 at 23:53
  • 2
    Note that there is a difference in what is returned between this and the mapCanvas() technique Nathan mentions. The legendInterface() object will return all layers, even if they are not shown in the map canvas, while mapCanvas() returns only those shown on the canvas. Using mapCanvas() is a nice, quick way to get a reference to visible layers.
    – dakcarto
    May 27, 2012 at 2:00
  • 1
    On another note, the latest versions of QGIS (>= 1.8) allow the user to define a rendering order of layers separately from the order listed in the legend (very nice!). The legendInterface() and mapCanvas() methods return the layer order for each respectively.
    – dakcarto
    May 27, 2012 at 2:07
26

For QGIS 3, QgsMapLayerRegistry's functionality has been moved to QgsProject.

So, for iterating over map layers, you should use that structure:

layers = QgsProject.instance().mapLayers()

.mapLayers() returns a dictionary structured as {layer_x_id: layer_x, layer_y_id: layer_y, ....}. Then you can iterate over layers like:

for layer_id, layer in layers.items():
    print(layer.name())

Because .mapLayers() returns a dictionary (dict), you can also use .values() method of dictionary which returns just a list which contains layers in that case. Then you can iterate over layers like:

layers = QgsProject.instance().mapLayers().values()

for layer in layers:
    print(layer.name())

If you prefer, you can iterate in this way:

layers = QgsProject.instance().mapLayers() # dictionary

for layer in layers.values():
    print(layer.name())
3
  • Hi! Thanks for sharing it. To print the names of the layers works fine... but I can't print the keys of the dictionary. Can you help me with that?
    – Kajo
    Jun 18, 2019 at 18:39
  • 1
    for layer in layers: print(layer) You can use the script to print the keys. Or just use print(layers.keys()) without for loop. Jun 18, 2019 at 21:01
  • Hi @Kadir, how can I iterate in group's layers in QGIS 3 by name of group firstly, then with the nam's layer in this group?
    – nmokht97
    Jul 30, 2020 at 15:27
23

There are also two other ways:

layers = self.iface.mapCanvas().layers()

will give you a list of layers

or

layers = QgsMapLayerRegistry.instance().mapLayers()

for name, layer in layers.iteritems():
     print name, layer.type()
1
  • This answer doesn't seem to work in 2.16 and above
    – raphael
    Dec 28, 2016 at 21:27
16

For QGIS 2.6 here is the code to identify each layer and group them:

#make the desired groups for layers
toc = self.iface.legendInterface()
root = QgsProject.instance().layerTreeRoot()
group1 = root.insertGroup(0, "Group Point")
group2 = root.insertGroup(1, "Group Line")
group3 = root.insertGroup(2, "Group Polygon")
#get the list of layers  from registry
layers = QgsMapLayerRegistry.instance().mapLayers()
#segregate layers into groups 
for name, layer in layers.iteritems():
    # check the layer geometry type 
    if layer.geometryType() == QGis.Point:
        toc.moveLayer(layer, 0)

    if layer.geometryType() == QGis.Line:
        toc.moveLayer(layer, 1)

    if layer.geometryType() == QGis.Polygon:
        toc.moveLayer(layer, 2)

Note: After grouping I have to remove the duplicate layer so I used root.removeLayer(lyr).

0
6

Visible layers

You can iterate visible layers in this way:

# Iterate visible layers (warning: only spatial ones)
def iterate_visible_layers():
    for layer in iface.mapCanvas().layers():
        # TODO: Do something interesting with the layers
        print(layer.name())
    
iterate_visible_layers()

Layers in TOC (layers panel / legend / layer tree)

In case that you need all layers in the TOC/Layers-panel (not only those that are visible/checked, as mapCanvas().layers() returns), you can use this function:

# Iterate all ToC layers (warning: only spatial ones)
def iterate_toc_layers(group):
    for tree_layer in group.findLayers():
        # TODO: Do something interesting with the layers
        print(tree_layer.layer().name())

root = QgsProject.instance().layerTreeRoot()
iterate_toc_layers(root)

Note: You can iterate layers from a specific group by passing such a group to iterate_toc_layers(), in this way:

my_group = root.findGroup('My group')
iterate_toc_layers(my_group)

All registered layers

QGIS can use layers that are part of the QGIS project but are not shown in the TOC/Layers-panel. For instance, layers that can be used in joins or relationships (look-up tables). If you want to get those layers listed as well, do this:

# Iterate all registered layers (even if they aren't in the TOC)
def iterate_all_layers():
    for k, layer in QgsProject.instance().mapLayers().items():
        # TODO: Do something interesting with the layers
        print(layer.name())
            
iterate_all_layers()

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.