I have been working on a PyQGIS project for a bit, and I have been using QgsProject.instance().addMapLayer to add layers to the map.

However, now I need to add layers to my canvas and legend in specific groups, so I changed my logic for adding layers to the map to use the underlying QgsLayerTree object to add groups and add layers to those groups. I got it working, but it also introduced a new problem:

Whenever I add a layer to the map within a layer group using the new logic, the layer is not available whenever QGIS is restarted. The QgsLayerTreeLayer instances of the layers are still available, but it looks like they can't resolve their references to their source or other metadata. From what I can tell, it looks like they only have access to the layer ID.

How do I persist the layer tree between QGIS sessions? Or is there another way to implement adding layers within groups that would avoid this problem?

Adding Layers to Map

layer = QgsRasterLayer(...)
root = QgsProject.instance().layerTreeRoot()
group = root.insertGroup('Layers')
group.insertLayer(0, layer)

Reading Layers after QGIS Restart

root = QgsProject.instance().layerTreeRoot()
layer_tree_layers = root.findLayers()  # Returns list of QgsLayerTreeLayer objects

map_layers = []

for lyr in layer_tree_layers:
    map_layer = lyr.layer()  # Once QGIS has restarted, returns None!

I saw that in the QGIS API Documentation, it noted that the QgsLayerTreeLayer.layer() may return None/nullptr "...in the case of a layer node representing a layer which has not yet been fully loaded into a project, or a layer node representing a layer with an invalid data source...."

So why does my QGIS workspace persist normal map layers between instances, but not QgsLayerTreeLayers that were added to the map programmatically or is there an error in my logic that is causing this?

Note: The layers that I am loading into the map are QgsRasterLayers that have been read from geopackage tables. Didn't think it had anything to do with this because I am instantiating the layer objects from the source in the same way as I would any other layers. But just thought I'd mention it.


You still need to add the layer objects (and transfer their ownership) to the project. You can add the layer objects to the project first without adding them to the legend. The methods addMapLayer() and addMapLayers() both have a boolean parameter addToLegend which defaults to True. By passing False as the second argument, the layers will be added to the project but not the legend. You can then insert your group & layer nodes at the desired location in the layer tree.

For example:

layer_1 = QgsRasterLayer('path\\to\\layer_1', 'Raster_A')
layer_2 = QgsRasterLayer('path\\to\\layer_2', 'Raster_B')
QgsProject().instance().addMapLayers([layer_1, layer_2], False) # 2nd argument addToLegend=False
root = QgsProject().instance().layerTreeRoot()
group = root.insertGroup(0, 'Layers')
group.insertLayer(0, layer_1)
group.insertLayer(1, layer_2)
| improve this answer | |

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.