When QGIS 3.0 was release, I published a Processing script template for QGIS3. While the script template is nicely pythonic, it’s also pretty long and daunting for non-programmers. This fact didn’t go unnoticed and Nathan Woodrow in particular started to work on a QGIS enhancement proposal to improve the situation and make writing Processing scripts easier, while – at the same time – keeping in line with common Python styles.
While the previous template had 57 lines of code, the new template only has 26 lines – 50% less code, same functionality! (Actually, this template provides more functionality since it also tracks progress and ensures that the algorithm can be cancelled.)
from qgis.processing import alg
from qgis.core import QgsFeature, QgsFeatureSink
@alg(name="ex_new", label=alg.tr("Example script (new style)"), group="examplescripts", group_label=alg.tr("Example Scripts"))
@alg.input(type=alg.SOURCE, name="INPUT", label="Input layer")
@alg.input(type=alg.SINK, name="OUTPUT", label="Output layer")
def testalg(instance, parameters, context, feedback, inputs):
"""
Description goes here. (Don't delete this! Removing this comment will cause errors.)
"""
source = instance.parameterAsSource(parameters, "INPUT", context)
(sink, dest_id) = instance.parameterAsSink(
parameters, "OUTPUT", context,
source.fields(), source.wkbType(), source.sourceCrs())
total = 100.0 / source.featureCount() if source.featureCount() else 0
features = source.getFeatures()
for current, feature in enumerate(features):
if feedback.isCanceled():
break
out_feature = QgsFeature(feature)
sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total))
return {"OUTPUT": dest_id}
The key improvement are the new decorators that turn an ordinary function (such as testalg in the template) into a Processing algorithm. Decorators start with @
and are written above a function definition. The @alg
decorator declares that the following function is a Processing algorithm, defines its name and assigns it to an algorithm group. The @alg.input
decorator creates an input parameter for the algorithm. Similarly, there is a @alg.output
decorator for output parameters.
While the above example demonstrates how to process features individually by getting them from a source and writing them to a sink, some work flows may profit from dealing with layers instead. For example, see the PyQGIS101 tutorial on writing scripts that chain Processing tools.
For more about the @alg
decorator check out the official docs.
For a longer example script, check out the original QGIS enhancement proposal thread!
For now, this new way of writing Processing scripts is only supported by QGIS 3.6 but there are plans to back-port this improvement to 3.4 once it is more mature. So give it a try and report back!