1

I have a processing script (QGIS 3.12) that extracts values from an input table using the native:extractbyattribute algorithm. This produces a temporary output table with the display name 'Extracted (attribute) and I would like to rename this to something more meaningful within the script.

I can get the unique name of the layer with:

extracted = processing.run('native:extractbyattribute', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
layer = QgsProcessingUtils.mapLayerFromString(format(extracted['OUTPUT']), context )

but I can't see how to set the display name programmatically within the script. The layer is of type QgsVectorLayer. I can get its attributes with layer.dataProvider(), but this does not include a name attribute.

There are several ways to iterate through the layers from the console, but no information on how to do this through a script.

5 Answers 5

3

You need to use the QgsProcessingLayerPostProcessorInterface.postProcessLayer method to rename the layer after it has been added to the project. Using the QgsMapLayer.setName method has no effect. To use this, define a new class:

class Renamer (QgsProcessingLayerPostProcessorInterface):
    def __init__(self, layer_name):
        self.name = layer_name
        super().__init__()
        
    def postProcessLayer(self, layer, context, feedback):
        layer.setName(self.name)

Then in your code, create an instance of the class and attach it to the output layer:

    global renamer
    renamer = Renamer('DiffBuf')
    context.layerToLoadOnCompletionDetails(self.dest_id).setPostProcessor(renamer)

It is essential that you declare the variable holding the class as global, otherwise this will not work. self.dest_id in the code is the value of the second return value of parameterAsSink.

3
  • 1
    why is global necessary here? Commented Apr 14, 2022 at 16:50
  • 1
    By passing renamer to setPostProcessor you are passing an object whose postProcessLayer method will be called at a later time, outside this scope. If it's not declared global, it will not exist outside the scope in which it was defined,and thus you'll get an error. By declaring it global, you give the object global scope so that it will be valid when the method is invoked. If this is not making sense, read about scope of variables in Python.
    – Llaves
    Commented Apr 15, 2022 at 3:39
  • 1
    Got you, I spent hours before I come here and realized I am missing global. QGIS wasn't throwing an error, just not applying styles, which added to the confusion. Working fine now. Commented Apr 15, 2022 at 13:41
1

If I understood correctly the problem, you need to use the QgsMapLayer.setName() function (documentation here).

So, taking your code, you should be able to set the layer display name with:

layer.setName("LayerDisplayName")

Hope this helps.

0
1

The approach that works in my testing context (PS: I have thrown away the QgsProcessingUtils, not needed or I missed something)

This answer was an addition to solve the part you were stucked

Seems good, but the display name in the layers panel remains stubbornly 'Extracted (attribute)'.

I've used the file world_map.gpkg always present will all QGIS installation e.g https://twitter.com/geomenke/status/1034902521725083648 Hence, you can test with the same conditions as me by changing the path use in INPUT key from dictionary alg_params

from qgis.core import QgsProcessingContext, QgsProcessingFeedback, QgsProject

alg_params = { 'FIELD' : 'fid', 'INPUT' : '/usr/share/qgis/resources/data/world_map.gpkg|layername=countries', 'OPERATOR' : 4, 'OUTPUT' : 'TEMPORARY_OUTPUT', 'VALUE' : '1000' }

feedback = QgsProcessingFeedback()
context = QgsProcessingContext()
extracted = processing.run('native:extractbyattribute', alg_params, context=context, feedback=feedback, is_child_algorithm=False) # Changed is_child_algorithm=True to is_child_algorithm=False as it's a standalone example for the demo here
layer = extracted['OUTPUT']
print(layer.name()) # See it's the wrong name
layer.setName('My New Name') # Fix the name
QgsProject.instance().addMapLayer(layer) # Add the layer to the project to see it works
7
  • extracted['OUTPUT'] returns a string (name of created layer), so layer will be set to this string. Script complains 'layer' has no attribute 'name()'
    – TonyMJ
    Commented May 24, 2020 at 7:23
  • extracted['OUTPUT'] gives me <QgsMapLayer: 'Extracted (attribute)' (memory)> with the sample I provide, not a string
    – ThomasG77
    Commented May 24, 2020 at 7:33
  • Are you running this within a processing framework script?
    – TonyMJ
    Commented May 24, 2020 at 9:06
  • Not within PyQGIS console
    – ThomasG77
    Commented May 24, 2020 at 15:02
  • Your code works well when run from the console, but not when run from within a processing framework script. In this context type(layer) returns <class 'str'> . That's why I need to use layerNameFromString().
    – TonyMJ
    Commented May 24, 2020 at 15:28
0

That kind of works. I tried:

layer = QgsProcessingUtils.mapLayerFromString(format(extracted['OUTPUT']), context )
        feedback.pushInfo('\nLayer name is initially {}'. format(layer.name()))
        layer.setName('my_layer')
        feedback.pushInfo('\nLayer name is now {}'. format(layer.name()))

The first pushInfo call produces: 'The name of the layer is Extracted__attribute__627cdb7b_f503_4a62_b847_6264ef1ece33'

The second produces :'Layer name is now my_layer'

Seems good, but the display name in the layers panel remains stubbornly 'Extracted (attribute)'. So, the display name (which doesn't have to be unique) may not be the same as the layer name (which does).

0

Best approach for me has been this answer by lejedi76:

extracted = processing.run('native:extractbyattribute', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
layer_details = context.layerToLoadOnCompletionDetails(extracted['OUTPUT'])
layer_details.name = "Meaningful name"

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.