PyQGIS – How to Run Nested QGIS Processing Algorithm and Return String

pyqgisqgis-3qgis-processing

I am building a custom processing script using the QgsProcessingAlgorithm class.

In the early part of my algorithm, I am processing an input feature using the native 'centroids' algorithm. I want to access this output and continue with my algorithm, however the 'OUTPUT' key from the processing.run call only returns a string.

I initialize the input feature as:

   def initAlgorithm(self, config=None):
        """Defines input and output."""

        self.addParameter(
            QgsProcessingParameterFeatureSource(
                self.REFERENCE,
                "Choose input grid",
                [QgsProcessing.TypeVectorAnyGeometry]
                )
            )

and inside the processAlgorithm() method I use:

        # get centroids
        parameters_centroids = {
            "INPUT": parameters[self.REFERENCE],
            "ALL_PARTS": False,
            "OUTPUT": "memory":
        }
        centroids = processing.run("native:centroids", 
            parameters_centroids, is_child_algorithm=True,
            context=context, feedback=feedback)["OUTPUT"]
        if feedback.isCanceled():
            return {}
        
        feedback.pushInfo(f"{type(centroids)}")

The actual process runs without errors and gives feedback 'Results: {'OUTPUT': 'output_22428702_fd31_459d_9454_fce67f3e9f14'}' (or some other memory pointer).

The feedback.pushInfo() call gives <class 'str'> and prevents me from further processing the output from the centroids algorithm. I would expect the type to be a QgsVectorLayer.

Is this because of saving the output to 'memory:'?

This is an intermediate step in the algorithm I would happily avoid saving the centroids output. I believed loading layers only had to be done when processing from the console.

Best Answer

I found the solution looking at a related question.

The solution lies in retrieving the output layer into the processing script's context using the 'QgsProcessingContext' and its 'takeResultLayer' which can take a context and a memory id (string) as arguments. For me, it was used as follows


# get centroids
parameters_centroids = {
    "INPUT": parameters["REFERENCE"],
    "ALL_PARTS": False,
    "OUTPUT": "memory:"
}
centroids = processing.run("native:centroids", 
    parameters_centroids, is_child_algorithm=True,
    context=context, feedback=feedback)["OUTPUT"]
    if feedback.isCanceled():
        return {} 
centroids_layer = QgsProcessingContext.takeResultLayer(context, centroids) # type QgsVectorLayer

# centroids_layer can now be processed further.. like:
number_of_features = centroids_layer.featureCount()

note that context is an attribute of the processAlgorithm class using the current QGIS framework for processing scripts.

Related Question