Hi all, I have written a processing script for QGIS 3.x, which itself calls a native processing function (qgis:shortestpathpointtolayer) in a for loop.
--------- from qgis.PyQt.QtCore import QCoreApplication from qgis.core import (QgsProcessing, QgsFeatureRequest, QgsExpression, QgsProcessingContext, QgsProcessingException, QgsProcessingAlgorithm, QgsProcessingParameterVectorLayer, QgsProcessingFeatureSourceDefinition) from qgis import processing class findDownstreamPathAlgorithm(QgsProcessingAlgorithm): """ This is an algorithm that calculates downstream paths on a simplified network. """ INPUT_NETWORK = 'INPUT_NETWORK' INPUT_VALVES = 'INPUT_VALVES' def tr(self, string): return QCoreApplication.translate('Processing', string) def createInstance(self): return findDownstreamPathAlgorithm() def name(self): return 'iterateclusters' def displayName(self): return self.tr('Iterate clusters') def group(self): return self.tr('Thvilum') def groupId(self): return 'lukkelister' def shortHelpString(self): return self.tr("Iterate clusters in a simplified network") def initAlgorithm(self, config=None): self.addParameter( QgsProcessingParameterVectorLayer( self.INPUT_NETWORK, self.tr('Netværkslag'), [QgsProcessing.SourceType.TypeVectorLine] ) ) self.addParameter( QgsProcessingParameterVectorLayer( self.INPUT_VALVES, self.tr('Ventillag'), [QgsProcessing.SourceType.TypeVectorPoint] ) ) def processAlgorithm(self, parameters, context, feedback): # Retrieve the feature sources network = self.parameterAsVectorLayer( parameters, self.INPUT_NETWORK, context ) valves = self.parameterAsVectorLayer( parameters, self.INPUT_VALVES, context ) if network is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT_NETWORK)) if valves is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT_VALVES)) # Store inlets from valves layer in separate scractch layer inlets = valves.materialize(QgsFeatureRequest(QgsExpression("situation = 'IsInlet'"))) # Collect clusters to evaluate clusterList = [] for feat in network.getFeatures(): clusterList.append(feat["cluster"]) # Remove duplicates and sort list clusterList = sorted(set(clusterList)) if len(clusterList) > 0: total = 100.0 / len(clusterList) else: total = 0 isCanceled = False for current, cluster in enumerate(clusterList): # Update the progress bar feedback.setProgress(int(current * total)) valves.selectByExpression("cluster = {} and situation = 'Flow'".format(cluster)) for feat in valves.selectedFeatures(): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): isCanceled = True break vertex_id = feat["vertexId"] valve_geom = feat.geometry() network.selectByExpression("cluster != {}".format(cluster)) parameters = { 'DEFAULT_DIRECTION' : 2, 'DEFAULT_SPEED' : 50, 'DIRECTION_FIELD' : '', 'END_POINTS' : inlets, 'INPUT' : QgsProcessingFeatureSourceDefinition( network.id(), selectedFeaturesOnly=True), 'OUTPUT' : 'TEMPORARY_OUTPUT', #'OUTPUT_NON_ROUTABLE' : 'TEMPORARY_OUTPUT', 'SPEED_FIELD' : '', 'START_POINT' : valve_geom, 'STRATEGY' : 0, 'TOLERANCE' : 0, 'VALUE_BACKWARD' : '', 'VALUE_BOTH' : '', 'VALUE_FORWARD' : '' } result = processing.run("qgis:shortestpathpointtolayer", parameters, context=context, feedback=feedback, is_child_algorithm=True) shortest_path = QgsProcessingContext.takeResultLayer(context, result['OUTPUT']) # Do something with the path del shortest_path if isCanceled: break return {self.INPUT_NETWORK: network} --------- When running this script on QGIS 3.28.4 it runs a couple of iterations and then raises an exception (access violation) with the following description: **Python Stack Trace** ``` Windows fatal exception: access violation Thread 0x00005d8c (most recent call first): File "C:\PROGRA~1/QGIS32~2.4/apps/qgis-ltr/./python/plugins\processing\gui\Algori thmExecutor.py", line 72 in execute results, ok = alg.run(parameters, context, feedback, {}, False) File "C:\PROGRA~1/QGIS32~2.4/apps/qgis-ltr/./python/plugins\processing\core\Proce ssing.py", line 187 in runAlgorithm ret, results = execute(alg, parameters, context, feedback, catch_exceptions=False) File "C:\PROGRA~1/QGIS32~2.4/apps/qgis-ltr/./python/plugins\processing\tools\gene ral.py", line 116 in run return Processing.runAlgorithm(algOrName, parameters, onFinish=post_process, feedback=feedback, context=context) File "C:\Users\morte\AppData\Roaming\QGIS\QGIS3\profiles\default\processing\scrip ts\iterateClusters.py", line 156 in processAlgorithm result = processing.run("qgis:shortestpathpointtolayer", parameters, context=context, feedback=feedback, is_child_algorithm=True) Current thread 0x000075e0 (most recent call first): File "C:\PROGRA~1/QGIS32~2.4/apps/qgis-ltr/./python/plugins\processing\Processing Plugin.py", line 394 in executeAlgorithm dlg.exec_() File "C:\PROGRA~1/QGIS32~2.4/apps/qgis-ltr/./python/plugins\processing\gui\Proces singToolbox.py", line 234 in executeAlgorithm self.executeWithGui.emit(alg.id(), self, self.in_place_mode, False) ``` On QGIS 3.38.3 the process also runs for a couple of iteration and then just freezes the whole application. Running a simple (=non processing) version of this script from the Python console works beautifully on both QGIS versions! What am I missing in my processing script? Best regards, Morten -- Morten Storm Styrke 10 ApS House of Innovation | Jernbanegade 27 | 6000 Kolding | Denmark www: https://styrke10.dk mobile: +45 51 51 09 29 _______________________________________________ QGIS-User mailing list QGIS-User@lists.osgeo.org List info: https://lists.osgeo.org/mailman/listinfo/qgis-user Unsubscribe: https://lists.osgeo.org/mailman/listinfo/qgis-user