Processing script template for QGIS3

Processing has been overhauled significantly for QGIS 3.0. Besides speed-ups, one of the most obvious changes is the way to write Processing scripts. Instead of the old Processing-specific syntax, Processing scripts for QGIS3 are purely pythonic implementations of QgsProcessingAlgorithm.

Here’s a template that you can use to develop your own algorithms:

from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsField, QgsFeature, QgsFeatureSink, QgsFeatureRequest, QgsProcessing, QgsProcessingAlgorithm, QgsProcessingParameterFeatureSource, QgsProcessingParameterFeatureSink)
                      
class ExAlgo(QgsProcessingAlgorithm):
    INPUT = 'INPUT'
    OUTPUT = 'OUTPUT'

    def __init__(self):
        super().__init__()

    def name(self):
        return "exalgo"
    
    def tr(self, text):
        return QCoreApplication.translate("exalgo", text)
        
    def displayName(self):
        return self.tr("Example script")

    def group(self):
        return self.tr("Examples")

    def groupId(self):
        return "examples"

    def shortHelpString(self):
        return self.tr("Example script without logic")

    def helpUrl(self):
        return "https://qgis.org"
        
    def createInstance(self):
        return type(self)()
  
    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterFeatureSource(
            self.INPUT,
            self.tr("Input layer"),
            [QgsProcessing.TypeVectorAnyGeometry]))
        self.addParameter(QgsProcessingParameterFeatureSink(
            self.OUTPUT,
            self.tr("Output layer"),
            QgsProcessing.TypeVectorAnyGeometry))

    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               source.fields(), source.wkbType(), source.sourceCrs())

        features = source.getFeatures(QgsFeatureRequest())
        for feat in features:
            out_feat = QgsFeature()
            out_feat.setGeometry(feat.geometry())
            out_feat.setAttributes(feat.attributes())
            sink.addFeature(out_feat, QgsFeatureSink.FastInsert)

        return {self.OUTPUT: dest_id}

This script just copies the features of the input layer to the output layer without any modifications. Add your logic to the processAlgorithm() function to get started.

Use Create New Script from the Toolbox toolbar:

Paste the example script:

Once saved, the script will show up in the Processing toolbox:

12 comments
  1. Ramamohan said:

    I find your articles very timely and easier to understand. I just read your review article on Profile tool plugin. Will you be able to write also on Qepanet plugin. Another area is snapping and topology options in QGIS 3.0. We find some of the options (like ‘enable topological editing’ option in 2.18) missing in 3.0. Are there any automatic snapping plugins available in 3.0 for perfect matching of boundaries of polygons ?

    • Thank you Ramamohan! I’ll look into that plugin. Snapping options are in the Project menu in QGIS3.

  2. Phil said:

    Thank you so much, Anita! This is exactly what I was looking for. Do you know of any other resources for writing processing scripts in QGIS3 specifically? I’m new to writing processing scripts in QGIS and I’m finding a fair amount of stuff for how to do it in QGIS2, but not much for QGIS3. Thanks again, you’ve already been a huge help!

  3. Tohan said:

    Thanks, this has been a huge help!
    I need to call an existing Algorithm to be applied to my current output, would you mind sharing some directions ?
    I understand this could be done through the modeler but my Algorithm really feels unfinished without it so it would really make more sense to have this external call included.

  4. Stefan Giese said:

    Dear Anita,
    very helpful – thanks for the starting point for processing scripts, since there is nearly no documentation at the moment about this.

    • Thanks Stefan. In the next version of QGIS, a template will be included by default.

  5. Shawn Carter said:

    Dear Anita,
    Thank you for this guide and getting a ‘Create script from template’ in 3.2.0. I feel like I’m missing something fundamental in understanding how values are passed from the tool window to the processing algorithm. So far, all the templates and guides I’ve found are based on this example, but what about a text input? For example, I only need start date-time and end date-time for my script (it will retrieve all the files and model data to verify our climate model against observed values). In my initAlgorithm() class, I have changed the inputs as :

    QgsProcessingParameterString(self.START, self.tr(‘Model Start Time’), ‘YYYYMMDDHH’)

    Then, in the processAlgorithm() class, I tried to retrieve the start time with:
    start_time = self.parameterAsString(parameters, self.START, context)

    It returns this error:
    NoneType cannot be converted to a C/C++ QMap in this context

    Any idea of what I’m missing?

    • Did you put START = ‘START’ before the init() function definition (on line 7)?

      • Shawn Carter said:

        Yes. I didn’t realize that the processAlgorithm function had to return a dictionary, even an empty dictionary to not throw that error. Still solidly in the front of the struggle bus, but getting there, thanks!

  6. Jason said:

    Hello. I’m trying to insert an external interpolator into the model. The program is called from the console with a simple script:

    import os
    from subprocess import call
    os.chdir (“D:\\program”)
    call (‘interpol.exe’+’ ‘+’param.dat’)
    import os
    from subprocess import call
    os.chdir (“D:\\geoprog”)
    call (‘interpol.exe’+’ ‘+’param.dat’)

    Apllication uses text files as input, and on output gives a raster in the ASCII format. Output and input files are written in the parameter file (.dat)
    Is it possible to embed this application in QGIS 3?