24.7. Usare gli algoritmi di Processing dalla console dei comandi
La console permette ad utenti esperti di aumentare la propria produttività e di eseguire operazioni complesse che non possono essere eseguite utilizzando uno qualsiasi degli altri elementi dell’interfaccia grafica di Processing. I modelli che richiamano diversi algoritmi possono essere definiti utilizzando l’interfaccia della riga di comando, e le operazioni aggiuntive, come i loop e le frasi condizionali possono essere aggiunte per creare flussi di lavoro più flessibili e potenti.
Non c’è una console di processing in QGIS, ma tutti i comandi di processing sono invece resi disponibili dalla predefinita QGIS Python console. Ciò significa che puoi incorporare tali comandi nellal tuo console operativa e collegare gli algoritmi di elaborazione a tutte le altre funzionalità (inclusi i metodi delle API di QGIS) lì disponibili.
Il codice che puoi eseguire dalla console di python, anche se non richiama un metodo specifico di Processing, può essere convertito in un nuovo algoritmo che potrai richiamare in seguito dagli Strumenti, dal Modellatore grafico o da qualunque altra parte, proprio come ogni altro algoritmo. Alcuni algoritmi che trovi in Strumenti sono in effetti degli script semplici.
In questa sezione verrà spiegato come usare gli algoritmi di Processing dalla console di Python e anche come scrivere un algoritmo usando Python.
24.7.1. Richiamare algoritmi dalla console di python
La prima cosa da fare è importare le funzioni di Processing con la seguente istruzione:
>>> from qgis import processing
Ora, c’è fondamentalmente solo una cosa (interessante) che puoi fare dalla console: eseguire un algoritmo. Questo viene fatto usando il metodo run()
, che prende il nome dell’algoritmo da eseguire come primo parametro, e poi un numero variabile di parametri aggiuntivi a seconda dei requisiti dell’algoritmo. Quindi la prima cosa che devi conoscere è il nome dell’algoritmo da eseguire. Questo non è il nome che vedi nella casella degli strumenti, ma piuttosto un nome unico a riga di comando. Per trovare il nome giusto per il tuo algoritmo, puoi usare la processingRegistry
. Digita la seguente linea nella tua console:
>>> for alg in QgsApplication.processingRegistry().algorithms():
print(alg.id(), "->", alg.displayName())
Vedrai qualcosa del genere (con qualche trattino in più aggiunto per migliorare la leggibilità).
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
...
Questa è una lista di tutti gli ID degli algoritmi disponibili, ordinati per nome della fonte e nome dell’algoritmo, insieme ai loro nomi corrispondenti.
Una volta che sai il nome a riga di comando dell’algoritmo, la prossima cosa da fare è determinare la giusta sintassi per eseguirlo. Questo significa sapere quali parametri sono necessari quando si chiama il metodo run()
.
C’è un metodo per descrivere un algoritmo in dettaglio, che può essere usato per ottenere una lista dei parametri che un algoritmo richiede e gli output che genererà. Per ottenere queste informazioni, puoi usare il metodo algoritmoHelp(id_dell_algoritmo)
. Usa l’ID dell’algoritmo, non il nome descrittivo completo.
Richiamando il metodo con native:buffer
come parametro (qgis:buffer
è un alias di native:buffer
e funzionerà ugualmente), ottieni la seguente descrizione:
>>> 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
Ora hai tutto il necessario per eseguire qualsiasi algoritmo. Come abbiamo già detto, gli algoritmi possono essere eseguiti usando: run()
. La sua sintassi è la seguente:
>>> processing.run(name_of_the_algorithm, parameters)
Dove parameters è un dizionario di parametri che dipendono dall’algoritmo che vuoi eseguire, ed è esattamente la lista che il metodo algorithmHelp()
ti dà.
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 un parametro è opzionale e non vuoi usarlo, allora non includerlo nel dizionario.
Se un parametro non è specificato, verrà utilizzato il valore predefinito.
A seconda del tipo di parametro, i valori sono inseriti in maniera diversa. Il seguente elenco dà una rapida panoramica di come inserire valori per ogni tipo di parametro in input:
Layer Raster, Layer Vettoriale o Tabella. Basta usare una stringa con il nome che identifica il data object da usare (il nome che ha nella Table of Contents di QGIS) o un nome di file (se il layer corrispondente non è aperto, verrà aperto ma non aggiunto alla mappa). Se hai un’istanza di un oggetto QGIS che rappresenta il layer, puoi anche passarlo come parametro.
Conteggio. Se un algoritmo ha un parametro di conteggio, il valore di quel parametro dovrebbe essere inserito usando un valore intero. Per conoscere le opzioni disponibili, puoi usare il comando
algorithmHelp()
, come sopra. Per esempio, l’algoritmonative:buffer
ha una numerazione chiamata 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
In questo caso, il parametro ha tre opzioni. Da notare che l’ordine è su base zero.
Booleano. Usare
True
oFalse
.Input multipli. Il valore è una stringa con descrittori in input separati da un punto e virgola (
;
). Come nel caso di layer singoli o tabelle, ogni descrittore in input può essere il nome dell’oggetto o il suo percorso.Campo di una Tabella da XXX. Inserisci una stringa con il nome del campo da usare. Il parametro è sensibile alle lettere maiuscole.
Tabella fissa. Inserisci l’elenco di tutti i valori delle tabelle separati da una virgola (
,
) e racchiusi fra virgolette ("
). I valori partono dalla riga in alto e proseguono da sinistra verso destra. Puoi usare un array 2-D per i valori che rappresentano la tabella.SR. Inserisci il codice EPSG del SR desiderato.
Estensione. Usa un stringa con valori
xmin
,xmax
,ymin
eymax
separati da virgole (,
).
Parametri booleani, di file, di stringa e numerici non hanno bisogno di ulteriori spiegazioni.
I parametri di input come stringhe, booleani o valori numerici hanno valori predefiniti. Il valore predefinito viene utilizzato se la voce corrispondente del parametro è mancante.
Per i dati di output, digitare il percorso del file da utilizzare per salvarlo, proprio come si fa dal pannello degli strumenti. Se non viene specificato l’oggetto di output, il risultato viene salvato in un file temporaneo (o omesso se si tratta di un output opzionale). L’estensione del file determina il formato del file. Se si inserisce un’estensione di file non supportata dall’algoritmo, verrà utilizzato il formato di file predefinito per quel tipo di output, e la sua estensione corrispondente verrà aggiunta al percorso indicato.
A differenza di quando un algoritmo viene eseguito dagli strumenti di Processing, gli output non vengono aggiunti alla mappa se si esegue lo stesso algoritmo dalla console Python usando run()
, ma runAndLoadResults()
lo farà.
Il metodo run()
restituisce un dizionario con uno o più nomi in uscita (quelli mostrati nella descrizione dell’algoritmo) come chiavi e i percorsi dei file di tali nomi come valori:
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
Puoi caricare l’output delle funzioni passando i percorsi dei file corrispondenti al metodo load()
. Oppure puoi usare runAndLoadResults()
invece di run()
per caricarli immediatamente.
Se vuoi aprire un dialogo su un algoritmo dalla console puoi usare il metodo createAlgorithmDialog
. L’unico parametro obbligatorio è il nome dell’algoritmo, ma puoi anche definire il dizionario dei parametri in modo che il dialogo venga riempito automaticamente:
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()
Il metodo execAlgorithmDialog
apre immediatamente la finestra di dialogo:
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'})
24.7.2. Creare script ed eseguirli da Strumenti
Puoi creare i tuoi algoritmi scrivendo codice Python. Gli script di processing hanno una QgsProcessingAlgorithm
, quindi devi aggiungere alcune linee di codice extra per implementare le funzioni obbligatorie. Puoi trovare Create new script ( scheda pulita) e Create New Script from Template (template che include il codice per le funzioni obbligatorie di QgsProcessingAlgorithm
) sotto il menu a discesa Scripts in cima alla finestra degli strumenti di Processing. Si aprirà l’Editor di script di Processing, ed è lì che dovresti digitare il tuo codice. Salvando lo script da lì nella cartella scripts
(la cartella predefinita quando apri la finestra di dialogo di salvataggio del file) con un’estensione .py
dovrebbe creare l’algoritmo corrispondente.
Il nome dell’algoritmo (quello che vedrai nella casella degli strumenti) è definito all’interno del codice.
Diamo un’occhiata al seguente codice, che definisce un algoritmo di Processing che esegue un’operazione di buffer con una distanza di buffer definita dall’utente su un layer vettoriale che è specificato dall’utente, dopo aver prima smussato il 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}
Dopo aver fatto le importazioni necessarie, vengono specificate le seguenti funzioni QgsProcessingAlgorithm
:
name()
: L’id dell’algoritmo (minuscolo).displayName()
: Un nome interpretabile per l’algoritmo.createInstance()
: Crea una nuova istanza nella classe algoritmo.initAlgorithm()
: Configura la parameterDefinitions e outputDefinitions.Qui descrivi i parametri e l’output dell’algoritmo. In questo caso, una geometria per l’input, una geometria per il risultato e un numero per la distanza del buffer.
processAlgorithm()
: Esegue.Qui eseguiamo prima l’algoritmo
moothgeometry
per smussare la geometria, e poi eseguiamo l’algoritmobuffer
sull’output smussato. Per poter eseguire algoritmi dall’interno di un altro algoritmo dobbiamo impostare lil parametrois_child_algorithm
aTrue`
. Puoi vedere come i parametri di input e output sono usati come parametri per gli algoritmimoothgeometry
ebuffer
.
Ci sono diversi tipi di parametri disponibili per l’input e l’output. Di seguito c’è una lista in ordine alfabetico:
Il primo parametro è il nome del parametro e il secondo è la descrizione del parametro (per l’interfaccia utente). Il resto dei parametri sono specifici del tipo di parametro.
L’input può essere trasformato in classi QGIS usando le funzioni parameterAs
di QgsProcessingAlgorithm
. Per esempio per ottenere il numero fornito per la distanza del buffer come una doppia:
self.parameterAsDouble(parameters, self.INPUT_BUFFERDIST, context)).
La funzione processAlgorithm
dovrebbe restituire un dizionario contenente valori per ogni output definito dall’algoritmo. Questo permette di accedere a questi output da altri algoritmi, compresi altri algoritmi contenuti nello stesso modello.
Gli algoritmi che si comportano bene dovrebbero definire e restituire tanti output quanti hanno importanza. Gli output non relativi alle funzionalità, come numeri e stringhe, sono molto utili quando si esegue l’algoritmo come parte di un modello più grande, poiché questi valori possono essere utilizzati come parametri di input per gli algoritmi successivi all’interno del modello. Si consideri l’aggiunta di output numerici per cose come il numero di elementi processati, il numero di elementi non validi incontrati, il numero di elementi in uscita, ecc. Più output restituite, più utile diventa il vostro algoritmo!
24.7.2.1. Feedback
L’oggetto feedback
passato a processAlgorithm()
dovrebbe essere usato per il feedback/interazione dell’utente. Puoi usare la funzione setProgress()
dell’oggetto feedback
per aggiornare la barra di avanzamento (da 0 a 100) per informare l’utente sul avanzamento dell’algoritmo. Questo è molto utile se il tuo algoritmo richiede molto tempo per essere completato.
L’oggetto feedback
fornisce un metodo isCanceled()
che dovrebbe essere monitorato per consentire la cancellazione dell’algoritmo da parte dell’utente. Il metodo pushInfo()
di feedback
può essere usato per inviare informazioni all’utente, e reportError()
è utile per inviare errori non fatali agli utenti.
Gli algoritmi dovrebbero evitare di usare altre forme per fornire feedback agli utenti, come istruzioni di stampa o di notifica a QgsMessageLog
, e dovrebbero invece usare sempre l’oggetto feedback. Questo permette un log dettagliato per l’algoritmo, ed è anche thread-safe (il che è importante, dato che gli algoritmi sono tipicamente eseguiti in un thread in background).
24.7.2.2. Gestire gli errori
Se il tuo algoritmo incontra un errore che ne impedisce l’esecuzione, come valori di input non validi o qualche altra condizione da cui non può o non dovrebbe recuperare, allora dovresti generare una QgsProcessingException
. Ad esempio:
if feature['value'] < 20:
raise QgsProcessingException('Invalid input value {}, must be >= 20'.format(feature['value']))
Cerca di evitare di generare QgsProcessingException
per errori non fatali (ad esempio quando una feature ha una geometria nulla), e invece segnala semplicemente questi errori tramite feedback.reportError()
e salta la stessa. Questo aiuta a rendere il tuo algoritmo «model-friendly», poiché evita di interrompere l’esecuzione di un intero algoritmo quando si incontra un errore non fatale.
24.7.2.3. Documentare gli script
Come nel caso dei modelli, puoi creare una documentazione aggiuntiva per i tuoi script, per spiegare cosa fanno e come usarli.
QgsProcessingAlgorithm
fornisce le funzioni per questo scopo helpString()
, shortHelpString()
e helpUrl()
. Specifica / sovrascrive queste funzioni per fornire più aiuto all’utente.
shortDescription()
è usato quando il puntatore del mouse passa sopra l’algoritmo nella casella degli strumenti.
24.7.3. Script agganciati pre e post esecuzione
Gli script possono anche essere usati come controlli pre- e post-esecuzione che vengono eseguiti rispettivamente prima e dopo l’esecuzione di un algoritmo. Questo può essere usato per automatizzare i processi che dovrebbero essere eseguiti ogni volta che un algoritmo viene eseguito.
La sintassi è identica alla sintassi spiegato sopra, ma hai a disposizione anche una variabile globale chiamata alg
che rappresenta l’algoritmo che è appena stato (o che sta per essere) eseguito.
Nel gruppo General della finestra di dialogo delle opzioni di processing, troverai due voci chiamate Pre-execution script e Post-execution script dove possono essere inseriti i nomi dei file degli script da eseguire caso per caso.