26.7. Usando os algoritmos do processamento a partir do Terminal Python.

O terminal permite que usuários avançados aumente sua produtividade e execute operações complexas que não podem ser utilizados através dos outros elementos GUI da caixa de processamento. Modelos envolvendo vários algoritmos podem ser definidos usando a interface de linha de comando e operações adicionais como loops e sentenças condicionais podem ser adicionados para criar fluxos de trabalho mais flexíveis e poderosos.

There is not a processing console in QGIS, but all processing commands are available instead from the QGIS built-in Python console. That means that you can incorporate those commands into your console work and connect processing algorithms to all the other features (including methods from the QGIS API) available from there.

O código que pode executar a partir do Terminal Python, mesmo quando não chama nenhum método específico do processamento, pode ser convertido num novo algoritmo que pode mais tarde chamar da caixa de ferramentas, o modelador gráfico ou qualquer outro componente, como faz para outro algoritmo. De fato, alguns algoritmos que encontra na caixa de ferramentas são scripts simples.

Nesta seção, veremos como usar algoritmos de processamento do console QGIS Python e também como escrever algoritmos usando Python.

26.7.1. Chamando os algoritmos a partir do Terminal Python

A primeira coisa que tem de fazer é importar as funções do processamento com a seguinte linha:

>>> from qgis import processing

Now, there is basically just one (interesting) thing you can do with that from the console: execute an algorithm. That is done using the run() method, which takes the name of the algorithm to execute as its first parameter, and then a variable number of additional parameters depending on the requirements of the algorithm. So the first thing you need to know is the name of the algorithm to execute. That is not the name you see in the toolbox, but rather a unique command–line name. To find the right name for your algorithm, you can use the processingRegistry. Type the following line in your console:

>>> for alg in QgsApplication.processingRegistry().algorithms():
        print(alg.id(), "->", alg.displayName())

Você verá algo assim (com alguns traços extras adicionados para melhorar a legibilidade).

3d:tessellate --------------> Tessellate
gdal:aspect ----------------> Aspect
gdal:assignprojection ------> Assign projection
gdal:buffervectors ---------> Buffer vectors
gdal:buildvirtualraster ----> Build Virtual Raster
gdal:cliprasterbyextent ----> Clip raster by extent
gdal:cliprasterbymasklayer -> Clip raster by mask layer
gdal:clipvectorbyextent ----> Clip vector by extent
gdal:clipvectorbypolygon ---> Clip vector by mask layer
gdal:colorrelief -----------> Color relief
gdal:contour ---------------> Contour
gdal:convertformat ---------> Convert format
gdal:dissolve --------------> Dissolve
...

Essa é uma lista de todos os IDs de algoritmo disponíveis, classificados por nome de provedor e nome de algoritmo, juntamente com seus nomes correspondentes.

Once you know the command-line name of the algorithm, the next thing to do is to determine the right syntax to execute it. That means knowing which parameters are needed when calling the run() method.

There is a method to describe an algorithm in detail, which can be used to get a list of the parameters that an algorithm requires and the outputs that it will generate. To get this information, you can use the algorithmHelp(id_of_the_algorithm) method. Use the ID of the algorithm, not the full descriptive name.

Calling the method with native:buffer as parameter (qgis:buffer is an alias for native:buffer and will also work), you get the following description:

>>> processing.algorithmHelp("native:buffer")
Buffer (native:buffer)

This algorithm computes a buffer area for all the features in an
input layer, using a fixed or dynamic distance.

The segments parameter controls the number of line segments to
use to approximate a quarter circle when creating rounded
offsets.

The end cap style parameter controls how line endings are handled
in the buffer.

The join style parameter specifies whether round, miter or
beveled joins should be used when offsetting corners in a line.

The miter limit parameter is only applicable for miter join
styles, and controls the maximum distance from the offset curve
to use when creating a mitered join.


----------------
Input parameters
----------------

INPUT: Input layer

   Parameter type: QgsProcessingParameterFeatureSource

   Accepted data types:
           - str: layer ID
           - str: layer name
           - str: layer source
           - QgsProcessingFeatureSourceDefinition
           - QgsProperty
           - QgsVectorLayer

DISTANCE: Distance

   Parameter type: QgsProcessingParameterDistance

   Accepted data types:
           - int
           - float
           - QgsProperty

SEGMENTS: Segments

   Parameter type: QgsProcessingParameterNumber

   Accepted data types:
           - int
           - float
           - QgsProperty

END_CAP_STYLE: End cap style

   Parameter type: QgsProcessingParameterEnum

   Available values:
           - 0: Round
           - 1: Flat
           - 2: Square

   Accepted data types:
           - int
           - str: as string representation of int, e.g. '1'
           - QgsProperty

JOIN_STYLE: Join style

   Parameter type: QgsProcessingParameterEnum

   Available values:
           - 0: Round
           - 1: Miter
           - 2: Bevel

   Accepted data types:
           - int
           - str: as string representation of int, e.g. '1'
           - QgsProperty

MITER_LIMIT: Miter limit

   Parameter type: QgsProcessingParameterNumber

   Accepted data types:
           - int
           - float
           - QgsProperty

DISSOLVE: Dissolve result

   Parameter type: QgsProcessingParameterBoolean

   Accepted data types:
           - bool
           - int
           - str
           - QgsProperty

OUTPUT: Buffered

   Parameter type: QgsProcessingParameterFeatureSink

   Accepted data types:
           - str: destination vector file, e.g. 'd:/test.shp'
           - str: 'memory:' to store result in temporary memory layer
           - str: using vector provider ID prefix and destination URI,
                  e.g. 'postgres:...' to store result in PostGIS table
           - QgsProcessingOutputLayerDefinition
           - QgsProperty

----------------
Outputs
----------------

OUTPUT:  <QgsProcessingOutputVectorLayer>
   Buffered

Now you have everything you need to run any algorithm. As we have already mentioned, algorithms can be run using: run(). Its syntax is as follows:

>>> processing.run(name_of_the_algorithm, parameters)

Where parameters is a dictionary of parameters that depend on the algorithm you want to run, and is exactly the list that the algorithmHelp() method gives you.

1 >>> processing.run("native:buffer", {'INPUT': '/data/lines.shp',
2               'DISTANCE': 100.0,
3               'SEGMENTS': 10,
4               'DISSOLVE': True,
5               'END_CAP_STYLE': 0,
6               'JOIN_STYLE': 0,
7               'MITER_LIMIT': 10,
8               'OUTPUT': '/data/buffers.shp'})

Se um parâmetro for opcional e você não quiser usá-lo, não o inclua no dicionário.

Se um parâmetro não for especificado, o valor padrão será usado.

Dependendo do tipo de parâmetro, os valores são introduzidos diferentemente. A próxima explicação é uma rápida revisão de como introduzir valores para cada tipo de parâmetro de entrada:

  • Raster Layer, Vector Layer or Table. Simply use a string with the name that identifies the data object to use (the name it has in the QGIS Table of Contents) or a filename (if the corresponding layer is not opened, it will be opened but not added to the map canvas). If you have an instance of a QGIS object representing the layer, you can also pass it as parameter.

  • Enumeration. If an algorithm has an enumeration parameter, the value of that parameter should be entered using an integer value. To know the available options, you can use the algorithmHelp() command, as above. For instance, the native:buffer algorithm has an enumeration called JOIN_STYLE:

    JOIN_STYLE: Join style
    
       Parameter type: QgsProcessingParameterEnum
    
       Available values:
               - 0: Round
               - 1: Miter
               - 2: Bevel
    
       Accepted data types:
               - int
               - str: as string representation of int, e.g. '1'
               - QgsProperty
    

    Neste caso, o parâmetro tem três opções. Observe que a ordem é baseada em zero.

  • Boleano. Use Verdadeiro ou Falso.

  • Múltiplas entradas. O valor é uma cadeia de texto com descritores de entrada separados por ponto e vírgula (;). Como no caso das camadas ou tabelas únicas, cada descritor de entrada pode ser o nome do objeto ou o caminho do arquivo.

  • Campo da Tabela de XXX. Use uma cadeia de texto com o nome do campo a usar. O parâmetro é caso sensitivo.

  • Tabela Fixa. Digite a lista de todos os valores da tabela separadas por vírgulas (,) e feche entre aspas ("). Os valores começam na linha superior e vai da esquerda para a direita. Pode também usar uma matriz 2D de valores que representam a tabela.

  • SRC. Introduza o número do código EPSG do SRC desejado.

  • Extensão. Deve usar uma cadeia de texto com xmin, xmax, ymin e ymax valores separados por vírgulas (,).

Os parâmetros booleanos, de arquivo, cadeia de texto e numéricos não necessitam de explicações adicionais.

Parâmetros de entrada como strings, booleanos ou valores numéricos têm valores padrão. O valor padrão é usado se a entrada de parâmetro correspondente estiver ausente.

For output data objects, type the file path to be used to save it, just as it is done from the toolbox. If the output object is not specified, the result is saved to a temporary file (or skipped if it is an optional output). The extension of the file determines the file format. If you enter a file extension not supported by the algorithm, the default file format for that output type will be used, and its corresponding extension appended to the given file path.

Unlike when an algorithm is executed from the toolbox, outputs are not added to the map canvas if you execute that same algorithm from the Python console using run(), but runAndLoadResults() will do that.

The run() method returns a dictionary with one or more output names (the ones shown in the algorithm description) as keys and the file paths of those outputs as values:

 1 >>> myresult = processing.run("native:buffer", {'INPUT': '/data/lines.shp',
 2               'DISTANCE': 100.0,
 3               'SEGMENTS': 10,
 4               'DISSOLVE': True,
 5               'END_CAP_STYLE': 0,
 6               'JOIN_STYLE': 0,
 7               'MITER_LIMIT': 10,
 8               'OUTPUT': '/data/buffers.shp'})
 9 >>> myresult['OUTPUT']
10 /data/buffers.shp

You can load feature output by passing the corresponding file paths to the load() method. Or you could use runAndLoadResults() instead of run() to load them immediately.

If you want to open an algorithm dialog from the console you can use the createAlgorithmDialog method. The only mandatory parameter is the algorithm name, but you can also define the dictionary of parameters so that the dialog will be filled automatically:

 1 >>> my_dialog = processing.createAlgorithmDialog("native:buffer", {
 2               'INPUT': '/data/lines.shp',
 3               'DISTANCE': 100.0,
 4               'SEGMENTS': 10,
 5               'DISSOLVE': True,
 6               'END_CAP_STYLE': 0,
 7               'JOIN_STYLE': 0,
 8               'MITER_LIMIT': 10,
 9               'OUTPUT': '/data/buffers.shp'})
10 >>> my_dialog.show()

The execAlgorithmDialog method opens the dialog immediately:

1 >>> processing.execAlgorithmDialog("native:buffer", {
2               'INPUT': '/data/lines.shp',
3               'DISTANCE': 100.0,
4               'SEGMENTS': 10,
5               'DISSOLVE': True,
6               'END_CAP_STYLE': 0,
7               'JOIN_STYLE': 0,
8               'MITER_LIMIT': 10,
9               'OUTPUT': '/data/buffers.shp'})

26.7.2. Criando scripts e correndo-os a partir da caixa de ferramentas

You can create your own algorithms by writing Python code. Processing scripts extend QgsProcessingAlgorithm, so you need to add some extra lines of code to implement mandatory functions. You can find Create new script (clean sheet) and Create New Script from Template (template that includes code for mandatory functions of QgsProcessingAlgorithm) under the Scripts dropdown menu on the top of the Processing toolbox. The Processing Script Editor will open, and that’s where you should type your code. Saving the script from there in the scripts folder (the default folder when you open the save file dialog) with a .py extension should create the corresponding algorithm.

O nome do algoritmo (o que você verá na caixa de ferramentas) é definido dentro do código.

Let’s have a look at the following code, which defines a Processing algorithm that performs a buffer operation with a user defined buffer distance on a vector layer that is specified by the user, after first smoothing the layer.

 1from qgis.core import (QgsProcessingAlgorithm,
 2       QgsProcessingParameterNumber,
 3       QgsProcessingParameterFeatureSource,
 4       QgsProcessingParameterFeatureSink)
 5
 6from qgis import processing
 7
 8class algTest(QgsProcessingAlgorithm):
 9    INPUT_BUFFERDIST = 'BUFFERDIST'
10    OUTPUT_BUFFER = 'OUTPUT_BUFFER'
11    INPUT_VECTOR = 'INPUT_VECTOR'
12
13    def __init__(self):
14        super().__init__()
15
16    def name(self):
17        return "algTest"
18
19    def displayName(self):
20        return "algTest script"
21
22    def createInstance(self):
23        return type(self)()
24
25    def initAlgorithm(self, config=None):
26        self.addParameter(QgsProcessingParameterFeatureSource(
27            self.INPUT_VECTOR, "Input vector"))
28        self.addParameter(QgsProcessingParameterNumber(
29            self.INPUT_BUFFERDIST, "Buffer distance",
30            QgsProcessingParameterNumber.Double,
31            100.0))
32        self.addParameter(QgsProcessingParameterFeatureSink(
33            self.OUTPUT_BUFFER, "Output buffer"))
34
35    def processAlgorithm(self, parameters, context, feedback):
36        #DO SOMETHING
37        algresult = processing.run("native:smoothgeometry",
38            {'INPUT': parameters[self.INPUT_VECTOR],
39             'ITERATIONS':2,
40             'OFFSET':0.25,
41             'MAX_ANGLE':180,
42             'OUTPUT': 'memory:'},
43            context=context, feedback=feedback, is_child_algorithm=True)
44        smoothed = algresult['OUTPUT']
45        algresult = processing.run('native:buffer',
46            {'INPUT': smoothed,
47            'DISTANCE': parameters[self.INPUT_BUFFERDIST],
48            'SEGMENTS': 5,
49            'END_CAP_STYLE': 0,
50            'JOIN_STYLE': 0,
51            'MITER_LIMIT': 10,
52            'DISSOLVE': True,
53            'OUTPUT': parameters[self.OUTPUT_BUFFER]},
54            context=context, feedback=feedback, is_child_algorithm=True)
55        buffered = algresult['OUTPUT']
56        return {self.OUTPUT_BUFFER: buffered}

After doing the necessary imports, the following QgsProcessingAlgorithm functions are specified:

  • name(): The id of the algorithm (lowercase).

  • displayName(): A human readable name for the algorithm.

  • createInstance(): Create a new instance of the algorithm class.

  • initAlgorithm(): Configure the parameterDefinitions and outputDefinitions.

    Here you describe the parameters and output of the algorithm. In this case, a feature source for the input, a feature sink for the result and a number for the buffer distance.

  • processAlgorithm(): Do the work.

    Here we first run the smoothgeometry algorithm to smooth the geometry, and then we run the buffer algorithm on the smoothed output. To be able to run algorithms from within another algorithm we have to set the is_child_algorithm argument to True. You can see how input and output parameters are used as parameters to the smoothgeometry and buffer algorithms.

Há uma série de diferentes tipos de parâmetros disponíveis para entrada e saída. Abaixo está uma lista em ordem alfabética:

Tabela 26.2 Lista de tipos de parâmetros de algoritmos de entrada e saída

QgsProcessingParameterAggregate

QgsProcessingParameterAnnotationLayer

QgsProcessingParameterAuthConfig

QgsProcessingParameterBand

QgsProcessingParameterBoolean

QgsProcessingParameterColor

QgsProcessingParameterCoordinateOperation

QgsProcessingParameterCrs

QgsProcessingParameterDatabaseSchema

QgsProcessingParameterDatabaseTable

QgsProcessingParameterDateTime

QgsProcessingParameterDistance

QgsProcessingParameterEnum

QgsProcessingParameterExpression

QgsProcessingParameterExtent

QgsProcessingParameterFeatureSink

QgsProcessingParameterFeatureSource

QgsProcessingParameterField

QgsProcessingParameterFieldMapping

QgsProcessingParameterFile

QgsProcessingParameterFileDestination

QgsProcessingParameterFolderDestination

QgsProcessingParameterGeometry

QgsProcessingParameterLayout

QgsProcessingParameterLayoutItem

QgsProcessingParameterMapLayer

QgsProcessingParameterMapTheme

QgsProcessingParameterMatrix

QgsProcessingParameterMeshLayer

QgsProcessingParameterMultipleLayers

QgsProcessingParameterNumber

QgsProcessingParameterPoint

QgsProcessingParameterPointCloudLayer

QgsProcessingParameterProviderConnection

QgsProcessingParameterRange

QgsProcessingParameterRasterDestination

QgsProcessingParameterRasterLayer

QgsProcessingParameterScale

QgsProcessingParameterString

QgsProcessingParameterVectorDestination

QgsProcessingParameterVectorLayer

QgsProcessingParameterVectorTileWriterLayers

O primeiro parâmetro para os construtores é o nome do parâmetro e o segundo é a descrição do parâmetro (para a interface do usuário). O restante dos parâmetros do construtor são específicos do tipo de parâmetro.

The input can be turned into QGIS classes using the parameterAs functions of QgsProcessingAlgorithm. For instance to get the number provided for the buffer distance as a double:

self.parameterAsDouble(parameters, self.INPUT_BUFFERDIST, context)).

The processAlgorithm function should return a dictionary containing values for every output defined by the algorithm. This allows access to these outputs from other algorithms, including other algorithms contained within the same model.

Well behaved algorithms should define and return as many outputs as makes sense. Non-feature outputs, such as numbers and strings, are very useful when running your algorithm as part of a larger model, as these values can be used as input parameters for subsequent algorithms within the model. Consider adding numeric outputs for things like the number of features processed, the number of invalid features encountered, the number of features output, etc. The more outputs you return, the more useful your algorithm becomes!

26.7.2.1. Feedback

The feedback object passed to processAlgorithm() should be used for user feedback / interaction. You can use the setProgress() function of the feedback object to update the progress bar (0 to 100) to inform the user about the progress of the algorithm. This is very useful if your algorithm takes a long time to complete.

The feedback object provides an isCanceled() method that should be monitored to enable cancelation of the algorithm by the user. The pushInfo() method of feedback can be used to send information to the user, and reportError() is handy for pushing non-fatal errors to users.

Algorithms should avoid using other forms of providing feedback to users, such as print statements or logging to QgsMessageLog, and should always use the feedback object instead. This allows verbose logging for the algorithm, and is also thread-safe (which is important, given that algorithms are typically run in a background thread).

26.7.2.2. Handling errors

If your algorithm encounters an error which prevents it from executing, such as invalid input values or some other condition from which it cannot or should not recover, then you should raise a QgsProcessingException. E.g.:

if feature['value'] < 20:
  raise QgsProcessingException('Invalid input value {}, must be >= 20'.format(feature['value']))

Try to avoid raising QgsProcessingException for non-fatal errors (e.g. when a feature has a null geometry), and instead just report these errors via feedback.reportError() and skip the feature. This helps make your algorithm “model-friendly”, as it avoids halting the execution of an entire algorithm when a non-fatal error is encountered.

26.7.2.3. Documentando os seus scripts

As in the case of models, you can create additional documentation for your scripts, to explain what they do and how to use them.

QgsProcessingAlgorithm provides the helpString(), shortHelpString() and helpUrl() functions for that purpose. Specify / override these to provide more help to the user.

shortDescription() is used in the tooltip when hovering over the algorithm in the toolbox.

26.7.3. Pré- e pós-execução de encaixe da script

Scripts can also be used as pre- and post-execution hooks that are run before and after an algorithm is run, respectively. This can be used to automate tasks that should be performed whenever an algorithm is executed.

A sintaxe é identica à sintaxe explicada em cima, mas uma variável global alg está disponível, representando o algoritmo que foi (ou está prestes a ser) executado.

In the General group of the processing options dialog, you will find two entries named Pre-execution script and Post-execution script where the filenames of the scripts to be run in each case can be entered.