2

I have lots of models in QGIS 3.8. I´m translating them to Python scripts to still use in the Tollbox but qith reduced processing time.

Using the QGIS automatic "export model as Python script", I´m having some trouble to get any shapefile that are not load in QGIS.

I made a simple model that merge two external shapefiles, that´s the export result:

from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterFeatureSink
import processing


class JustMerge(QgsProcessingAlgorithm):

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterFeatureSink('MergedOutput', 'Merged Output', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))

    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
        results = {}
        outputs = {}

        # Merge Layers
        alg_params = {
            'CRS': None,
            'LAYERS': [['C:/Shapes/File1.shp'],['C:/Shapes/File2.shp']],
            'OUTPUT': parameters['MergedOutput']
        }
        outputs['MergeLayers'] = processing.run('native:mergevectorlayers', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['MergedOutput'] = outputs['MergeLayers']['OUTPUT']
        return results

    def name(self):
        return 'Just Merge'

    def displayName(self):
        return 'Just Merge'

    def group(self):
        return 'Just Merge'

    def groupId(self):
        return 'Just Merge'

    def createInstance(self):
        return JustMerge()

I got this error only when running the Script, the original model works perfectly:

Processing algorithm…
Algorithm 'Just Merge' starting…
Input parameters:
{ 'MergedOutput' : 'TEMPORARY_OUTPUT' }

Traceback (most recent call last):
File "<string>", line 26, in processAlgorithm
File "C:/PROGRA~1/QGIS3~1.8/apps/qgis/./python/plugins\processing\tools\general.py", line 114, in run
return Processing.runAlgorithm(algOrName, parameters, onFinish=post_process, feedback=feedback, context=context)
File "C:/PROGRA~1/QGIS3~1.8/apps/qgis/./python/plugins\processing\core\Processing.py", line 136, in runAlgorithm
feedback.reportError(msg)
TypeError: reportError(self, error: str, fatalError: bool): not enough arguments

Execution failed after 0.04 seconds

Loading resulting layers
Algorithm 'Just Merge' finished

I´m looking for the right way to call the external files.

2

The underlying issue is that you're passing a list of list-of-strings as your layers parameter, not a list-of-strings.

I.e. instead of

   'LAYERS': [['C:/Shapes/File1.shp'],['C:/Shapes/File2.shp']],

You should be passing

   'LAYERS': ['C:/Shapes/File1.shp','C:/Shapes/File2.shp'],
1

Don't think it likes how you defined your input layers. You should consider using the new format for writing scripts as it gets rid off a lot of waffle. For example, the following script let's you select multiple shapefiles (either loaded in QGIS or external) and runs the merge tool. As it is a native tool, it would output the name of the tool used (at least that is the behavour I have noticed):

from qgis.processing import alg
from qgis.core import QgsFeature, QgsFeatureSink, QgsCoordinateReferenceSystem, QgsProject, QgsProcessingMultiStepFeedback
import processing

@alg(name="ex_new", label=alg.tr("Just Merge"), group="Just Merge", group_label=alg.tr("Just Merge"))
@alg.input(type=alg.MULTILAYER, name="INPUT", label="Input layer")
@alg.input(type=alg.VECTOR_LAYER_DEST, name="OUTPUT", label="Merged Output")
def testalg(instance, parameters, context, feedback, inputs):
    """
    Description goes here. (Don't delete this! Removing this comment will cause errors.)
    """        
    feedback = QgsProcessingMultiStepFeedback(1, feedback)

    # Merge Layers
    alg_params = {
        'LAYERS': parameters['INPUT'],
        'CRS': None,
        'OUTPUT': parameters['OUTPUT']
    }
    if feedback.isCanceled():
        return {}
    processing.run('native:mergevectorlayers', alg_params, is_child_algorithm=True, context=context, feedback=feedback)   

    return {}
  • Almost that. What I am looking for is to insert a file that is not declared as input, the user does not have the option to change this file, every time they execute, the same file will be selected. So I believe the @ alg.input method doesn't satisfy. I am reading your indication looking for answers. Thank you. – Herbert Santos Sep 11 at 15:41
1

I found it!

It´s need to define the files and call them by their names, not by their path.

        def processAlgorithm(self, parameters, context, model_feedback):

        File1 = 'C:/Shapes/File1.shp'
        File2 = 'C:/Shapes/File2.shp'

        # Merge Layers
        alg_params = {
            'CRS': None,
            'LAYERS': [File1,File2],
            'OUTPUT': parameters['MergedOutput']
        }

  • Glad you found the solution :) – Joseph Sep 17 at 9:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.