Viktigt
Översättning är en gemenskapsinsats du kan gå med i. Den här sidan är för närvarande översatt till 100.00%.
23.9. Skriva nya Processing-algoritmer som Python-skript
Det finns två alternativ för att skriva Processing-algoritmer med hjälp av Python.
Extending
QgsProcessingAlgorithm <qgis.core.QgsProcessingAlgorithm>`
I QGIS kan du använda Create new script i menyn Scripts högst upp i verktygslådan Processing Toolbox för att öppna Processing Script Editor där du kan skriva din kod. För att förenkla uppgiften kan du börja med en skriptmall genom att använda Create new script from template från samma meny. Detta öppnar en mall som utökar QgsProcessingAlgorithm
.
Om du sparar skriptet i mappen scripts
(standardplatsen) med tillägget .py
blir algoritmen tillgänglig i verktygslådan Processing Toolbox.
23.9.1. Förlängning av QgsProcessingAlgorithm
Följande kod
tar ett vektorlager som indata
räknar antalet funktioner
gör en buffertoperation
skapar ett rasterlager från resultatet av buffertoperationen
returnerar buffertlager, rasterlager och antal funktioner
1from qgis.PyQt.QtCore import QCoreApplication
2from qgis.core import (QgsProcessing,
3 QgsProcessingAlgorithm,
4 QgsProcessingException,
5 QgsProcessingOutputNumber,
6 QgsProcessingParameterDistance,
7 QgsProcessingParameterFeatureSource,
8 QgsProcessingParameterVectorDestination,
9 QgsProcessingParameterRasterDestination)
10from qgis import processing
11
12
13class ExampleProcessingAlgorithm(QgsProcessingAlgorithm):
14 """
15 This is an example algorithm that takes a vector layer,
16 creates some new layers and returns some results.
17 """
18
19 def tr(self, string):
20 """
21 Returns a translatable string with the self.tr() function.
22 """
23 return QCoreApplication.translate('Processing', string)
24
25 def createInstance(self):
26 # Must return a new copy of your algorithm.
27 return ExampleProcessingAlgorithm()
28
29 def name(self):
30 """
31 Returns the unique algorithm name.
32 """
33 return 'bufferrasterextend'
34
35 def displayName(self):
36 """
37 Returns the translated algorithm name.
38 """
39 return self.tr('Buffer and export to raster (extend)')
40
41 def group(self):
42 """
43 Returns the name of the group this algorithm belongs to.
44 """
45 return self.tr('Example scripts')
46
47 def groupId(self):
48 """
49 Returns the unique ID of the group this algorithm belongs
50 to.
51 """
52 return 'examplescripts'
53
54 def shortHelpString(self):
55 """
56 Returns a localised short help string for the algorithm.
57 """
58 return self.tr('Example algorithm short description')
59
60 def initAlgorithm(self, config=None):
61 """
62 Here we define the inputs and outputs of the algorithm.
63 """
64 # 'INPUT' is the recommended name for the main input
65 # parameter.
66 self.addParameter(
67 QgsProcessingParameterFeatureSource(
68 'INPUT',
69 self.tr('Input vector layer'),
70 types=[QgsProcessing.TypeVectorAnyGeometry]
71 )
72 )
73 self.addParameter(
74 QgsProcessingParameterVectorDestination(
75 'BUFFER_OUTPUT',
76 self.tr('Buffer output'),
77 )
78 )
79 # 'OUTPUT' is the recommended name for the main output
80 # parameter.
81 self.addParameter(
82 QgsProcessingParameterRasterDestination(
83 'OUTPUT',
84 self.tr('Raster output')
85 )
86 )
87 self.addParameter(
88 QgsProcessingParameterDistance(
89 'BUFFERDIST',
90 self.tr('BUFFERDIST'),
91 defaultValue = 1.0,
92 # Make distance units match the INPUT layer units:
93 parentParameterName='INPUT'
94 )
95 )
96 self.addParameter(
97 QgsProcessingParameterDistance(
98 'CELLSIZE',
99 self.tr('CELLSIZE'),
100 defaultValue = 10.0,
101 parentParameterName='INPUT'
102 )
103 )
104 self.addOutput(
105 QgsProcessingOutputNumber(
106 'NUMBEROFFEATURES',
107 self.tr('Number of features processed')
108 )
109 )
110
111 def processAlgorithm(self, parameters, context, feedback):
112 """
113 Here is where the processing itself takes place.
114 """
115 # First, we get the count of features from the INPUT layer.
116 # This layer is defined as a QgsProcessingParameterFeatureSource
117 # parameter, so it is retrieved by calling
118 # self.parameterAsSource.
119 input_featuresource = self.parameterAsSource(parameters,
120 'INPUT',
121 context)
122 numfeatures = input_featuresource.featureCount()
123
124 # Retrieve the buffer distance and raster cell size numeric
125 # values. Since these are numeric values, they are retrieved
126 # using self.parameterAsDouble.
127 bufferdist = self.parameterAsDouble(parameters, 'BUFFERDIST',
128 context)
129 rastercellsize = self.parameterAsDouble(parameters, 'CELLSIZE',
130 context)
131 if feedback.isCanceled():
132 return {}
133 buffer_result = processing.run(
134 'native:buffer',
135 {
136 # Here we pass on the original parameter values of INPUT
137 # and BUFFER_OUTPUT to the buffer algorithm.
138 'INPUT': parameters['INPUT'],
139 'OUTPUT': parameters['BUFFER_OUTPUT'],
140 'DISTANCE': bufferdist,
141 'SEGMENTS': 10,
142 'DISSOLVE': True,
143 'END_CAP_STYLE': 0,
144 'JOIN_STYLE': 0,
145 'MITER_LIMIT': 10
146 },
147 # Because the buffer algorithm is being run as a step in
148 # another larger algorithm, the is_child_algorithm option
149 # should be set to True
150 is_child_algorithm=True,
151 #
152 # It's important to pass on the context and feedback objects to
153 # child algorithms, so that they can properly give feedback to
154 # users and handle cancelation requests.
155 context=context,
156 feedback=feedback)
157
158 # Check for cancelation
159 if feedback.isCanceled():
160 return {}
161
162 # Run the separate rasterization algorithm using the buffer result
163 # as an input.
164 rasterized_result = processing.run(
165 'qgis:rasterize',
166 {
167 # Here we pass the 'OUTPUT' value from the buffer's result
168 # dictionary off to the rasterize child algorithm.
169 'LAYER': buffer_result['OUTPUT'],
170 'EXTENT': buffer_result['OUTPUT'],
171 'MAP_UNITS_PER_PIXEL': rastercellsize,
172 # Use the original parameter value.
173 'OUTPUT': parameters['OUTPUT']
174 },
175 is_child_algorithm=True,
176 context=context,
177 feedback=feedback)
178
179 if feedback.isCanceled():
180 return {}
181
182 # Return the results
183 return {'OUTPUT': rasterized_result['OUTPUT'],
184 'BUFFER_OUTPUT': buffer_result['OUTPUT'],
185 'NUMBEROFFEATURES': numfeatures}
Standardfunktioner för bearbetningsalgoritm:
- createInstance (obligatorisk)
Måste returnera en ny kopia av din algoritm. Om du ändrar namnet på klassen, se till att du också uppdaterar det värde som returneras här för att matcha!
- namn (obligatoriskt)
Returnerar det unika algoritmnamnet som används för att identifiera algoritmen.
- displayName (obligatoriskt)
Returnerar det översatta algoritmnamnet.
- group
Returnerar namnet på den grupp som den här algoritmen tillhör.
- groupId
Returnerar det unika ID:t för den grupp som den här algoritmen tillhör.
- shortHelpString
Returnerar en lokaliserad kort hjälpsträng för algoritmen.
- initAlgorithm (obligatorisk)
Här definierar vi algoritmens in- och utgångar.
INPUT
ochOUTPUT
är rekommenderade namn för huvudparametrarna för inmatning respektive utmatning.Om en parameter är beroende av en annan parameter används
parentParameterName
för att ange detta förhållande (kan vara fältet/bandet för ett lager eller avståndsenheterna för ett lager).
- processAlgorithm (obligatorisk)
Det är här som bearbetningen sker.
Parametrar hämtas med hjälp av specialfunktioner, t.ex.
parameterAsSource
ochparameterAsDouble
.processing.run
kan användas för att köra andra bearbetningsalgoritmer från en bearbetningsalgoritm. Den första parametern är namnet på algoritmen, den andra är en ordbok med parametrarna för algoritmen.is_child_algorithm
sätts normalt tillTrue
när en algoritm körs från en annan algoritm.context
ochfeedback
informerar algoritmen om den miljö den ska köras i och kanalen för att kommunicera med användaren (fånga upp begäran om avbrytande, rapportera framsteg, ge textuell feedback). När (föräldra)algoritmens parametrar används som parametrar för ”underordnade” algoritmer, skall de ursprungliga parametervärdena användas (t.ex.parameters['OUTPUT']
).Det är god praxis att kontrollera feedbackobjektet för annullering så mycket som det rimligen är möjligt! Detta gör det möjligt att avbryta på ett smidigt sätt, istället för att tvinga användarna att vänta på att en oönskad behandling ska ske.
Algoritmen ska returnera värden för alla utdataparametrar som den har definierat som en ordbok. I det här fallet är det buffert- och rastrerade utdatalager samt antalet bearbetade funktioner. Ordbokens nycklar måste matcha de ursprungliga parameter-/utdatanamnen.
23.9.2. @alg-dekoratorn
Med hjälp av @alg-dekoratorn kan du skapa dina egna algoritmer genom att skriva Python-koden och lägga till några extra rader för att tillhandahålla ytterligare information som behövs för att göra den till en riktig Processing-algoritm. Detta förenklar skapandet av algoritmer och specifikationen av in- och utgångar.
En viktig begränsning med dekoratormetoden är att algoritmer som skapas på detta sätt alltid kommer att läggas till i användarens Processing Scripts-provider - det är inte möjligt att lägga till dessa algoritmer i en anpassad provider, t.ex. för användning i plugins.
Följande kod använder @alg-dekoratorn för att
använda ett vektorlager som indata
räkna antalet funktioner
göra en buffertoperation
skapa ett rasterlager från resultatet av buffertoperationen
returnerar buffertlager, rasterlager och antal funktioner
1from qgis import processing
2from qgis.processing import alg
3from qgis.core import QgsProject
4
5@alg(name='bufferrasteralg', label='Buffer and export to raster (alg)',
6 group='examplescripts', group_label='Example scripts')
7# 'INPUT' is the recommended name for the main input parameter
8@alg.input(type=alg.SOURCE, name='INPUT', label='Input vector layer')
9# 'OUTPUT' is the recommended name for the main output parameter
10@alg.input(type=alg.RASTER_LAYER_DEST, name='OUTPUT',
11 label='Raster output')
12@alg.input(type=alg.VECTOR_LAYER_DEST, name='BUFFER_OUTPUT',
13 label='Buffer output')
14@alg.input(type=alg.DISTANCE, name='BUFFERDIST', label='BUFFER DISTANCE',
15 default=1.0)
16@alg.input(type=alg.DISTANCE, name='CELLSIZE', label='RASTER CELL SIZE',
17 default=10.0)
18@alg.output(type=alg.NUMBER, name='NUMBEROFFEATURES',
19 label='Number of features processed')
20
21def bufferrasteralg(instance, parameters, context, feedback, inputs):
22 """
23 Description of the algorithm.
24 (If there is no comment here, you will get an error)
25 """
26 input_featuresource = instance.parameterAsSource(parameters,
27 'INPUT', context)
28 numfeatures = input_featuresource.featureCount()
29 bufferdist = instance.parameterAsDouble(parameters, 'BUFFERDIST',
30 context)
31 rastercellsize = instance.parameterAsDouble(parameters, 'CELLSIZE',
32 context)
33 if feedback.isCanceled():
34 return {}
35 buffer_result = processing.run('native:buffer',
36 {'INPUT': parameters['INPUT'],
37 'OUTPUT': parameters['BUFFER_OUTPUT'],
38 'DISTANCE': bufferdist,
39 'SEGMENTS': 10,
40 'DISSOLVE': True,
41 'END_CAP_STYLE': 0,
42 'JOIN_STYLE': 0,
43 'MITER_LIMIT': 10
44 },
45 is_child_algorithm=True,
46 context=context,
47 feedback=feedback)
48 if feedback.isCanceled():
49 return {}
50 rasterized_result = processing.run('qgis:rasterize',
51 {'LAYER': buffer_result['OUTPUT'],
52 'EXTENT': buffer_result['OUTPUT'],
53 'MAP_UNITS_PER_PIXEL': rastercellsize,
54 'OUTPUT': parameters['OUTPUT']
55 },
56 is_child_algorithm=True, context=context,
57 feedback=feedback)
58 if feedback.isCanceled():
59 return {}
60 return {'OUTPUT': rasterized_result['OUTPUT'],
61 'BUFFER_OUTPUT': buffer_result['OUTPUT'],
62 'NUMBEROFFEATURES': numfeatures}
Som du kan se handlar det om två algoritmer (’native:buffer’ och ’qgis:rasterize’). Den sista (’qgis:rasterize’) skapar ett rasterlager från det buffertlager som genererades av den första (’native:buffer’).
Den del av koden där denna bearbetning sker är inte svår att förstå om du har läst föregående kapitel. De första raderna kräver dock lite extra förklaring. De innehåller den information som behövs för att omvandla din kod till en algoritm som kan köras från någon av GUI-komponenterna, t.ex. verktygslådan eller modelldesignern.
Dessa rader är alla anrop till dekoratorfunktionerna @alg
som hjälper till att förenkla kodningen av algoritmen.
Dekoratorn @alg används för att definiera algoritmens namn och plats i verktygslådan.
Dekoratorn @alg.input används för att definiera algoritmens ingångar.
Dekoratorn @alg.output används för att definiera algoritmens utdata.
För befintliga parametrar och deras motsvarighet, läs Inmatnings- och utmatningstyper för bearbetningsalgoritmer.
23.9.3. Utmatning av algoritm för överlämning
När du deklarerar en utdata som representerar ett lager (raster eller vektor) kommer algoritmen att försöka lägga till det i QGIS när den är klar.
Utmatning av rasterskikt: QgsProcessingParameterRasterDestination / alg.RASTER_LAYER_DEST.
Vektorskiktets utgång: QgsProcessingParameterVectorDestination / alg.VECTOR_LAYER_DEST.
Så även om metoden processing.run()
inte lägger till de lager som skapas i användarens aktuella projekt, kommer de två utdatalagren (buffert och rasterbuffert) att laddas, eftersom de sparas till de destinationer som användaren anger (eller till tillfälliga destinationer om användaren inte anger några destinationer).
Om ett lager skapas som resultat av en algoritm bör det deklareras som sådant. Annars kommer du inte att kunna använda algoritmen på rätt sätt i modelleraren, eftersom det som deklareras inte kommer att stämma överens med vad algoritmen verkligen skapar.
Du kan returnera strängar, tal och annat genom att ange dem i resultatordlistan (som visas för ”NUMBEROFFEATURES”), men de ska alltid uttryckligen definieras som utdata från din algoritm. Vi uppmuntrar algoritmer att ge ut så många användbara värden som möjligt, eftersom dessa kan vara värdefulla för användning i senare algoritmer när din algoritm används som en del av en modell.
23.9.4. Kommunicera med användaren
Om din algoritm tar lång tid att bearbeta är det en bra idé att informera användaren om framstegen. Du kan använda feedback
(QgsProcessingFeedback
) för detta.
Förloppstexten och förloppsfältet kan uppdateras med två metoder: setProgressText(text)
och setProgress(percent)
.
Du kan ge mer information genom att använda pushCommandInfo(text)
, pushDebugInfo(text)
, pushInfo(text)
och reportError(text)
.
Om ditt skript har ett problem är det korrekta sättet att hantera det att skapa ett QgsProcessingException
. Du kan skicka ett meddelande som ett argument till konstruktören för undantaget. Processing tar hand om hanteringen och kommunikationen med användaren, beroende på varifrån algoritmen körs (verktygslåda, modellerare, Python-konsol, …)
23.9.5. Dokumentera dina skript
Du kan dokumentera dina skript genom att överbelasta metoderna helpString()
och helpUrl()
i QgsProcessingAlgorithm
.
23.9.6. Flaggor
Du kan åsidosätta metoden flags()
i QgsProcessingAlgorithm
för att berätta mer för QGIS om din algoritm. Du kan t.ex. tala om för QGIS att skriptet ska döljas för modelleraren, att det kan avbrytas, att det inte är trådsäkert och mycket mer.
Tips
Som standard kör Processing algoritmer i en separat tråd för att hålla QGIS responsivt medan bearbetningsuppgiften körs. Om din algoritm kraschar regelbundet använder du förmodligen API-anrop som inte är säkra att göra i en bakgrundstråd. Försök att returnera flaggan QgsProcessingAlgorithm.FlagNoThreading från din algoritms flags()-metod för att tvinga Processing att köra din algoritm i huvudtråden istället.
23.9.7. Bästa praxis för att skriva skriptalgoritmer
Här är en snabb sammanfattning av idéer att tänka på när du skapar dina skriptalgoritmer och, särskilt, om du vill dela dem med andra QGIS-användare. Genom att följa dessa enkla regler säkerställs enhetlighet mellan de olika bearbetningselementen, t.ex. verktygslådan, modelleraren eller gränssnittet för batchbearbetning.
Ladda inte resulterande lager. Låt Processing hantera dina resultat och ladda dina lager om det behövs.
Deklarera alltid de utdata som din algoritm skapar.
Visa inte meddelanderutor eller använd något GUI-element från skriptet. Om du vill kommunicera med användaren använder du metoderna i feedback-objektet (
QgsProcessingFeedback
) eller kastar enQgsProcessingException
.
Det finns redan många bearbetningsalgoritmer tillgängliga i QGIS. Du kan hitta kod på QGIS repo.