2

Following up on this question, I need to be able to setup the QgsVectorLayer loaded via the delimitedtext provider as my algorithm output.

Note that I am still working from this template.
For lack of a better idea, I have defined (in initAlgorithm) the output like so:

self.addParameter(
    QgsProcessingParameterVectorDestination(
        self.OUTPUT,
        self.tr('Output'),
        type = QgsProcessing.TypeVectorAnyGeometry
    )
)

And my Algorithm currently looks like this:

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

    ## Define some parameters and functions to handle the loaded file.

    # Getting parameters values to local variables
    crs = self.parameterAsCrs(parameters, self.CRS, context)
    inputFile = self.parameterAsFile(parameters, self.FILEIN, context)
    ver = self.parameterAsEnum(parameters, self.VERSION, context)

    dest_id = self.parameterAsOutputLayer(parameters, self.OUPUT, context)

    uri = ('file:///{}?'
              'type=regexp'
              '&delimiter={}'
              '&skipLines={}'
              '&useHeader=No'
              '&trimFields=Yes'
              '&xField={}'
              '&yField={}'
              '&crs={}'
              '&spatialIndex=Yes'
              '&subsetIndex=no'
              '&watchFile=Yes').format(inputFile,
                                       regex,
                                       skips,
                                       'Easting',
                                       'Northing',
                                       crs.geographicCrsAuthId())

    vl = QgsVectorLayer(uri, 'MY_LAYER',  'delimitedtext')

    # Setup Fields Aliases
    for idx, alias in enumerate(myFields):
        try:
            vl.setFieldAlias(idx, alias)
        except:
            continue

    return {'MY_LAYER': dest_id}

The return line is where the crash happens but I'm running out of ideas: by comparison with the template where self.parameterAsSink() returned a tuple (sink, dest_id), I'm guessing the self.parameterAsOutputLayer() returns the dest_id.
Then I try to return the created layer vl and associate it with the dest_id, again, by analogy with the template.

I am stuck here as Qgis (3.0.2) crashes (right at the return line, every line of code gets executed without problem) every time I try to run this current code (but I can make it work fine as a standalone script from the Python Console...)

I have tried the following variations and all lead to invariable crashing:
return 'MY_LAYER'
return {vl: dest_id}
return {dest_id}
return dest_id
return vl
return

3

Because your output here is effectively hard-coded, you don't need to define it as a input parameter. Instead declare it as an output that your algorithm generates:

self.addOutput(
    QgsProcessingOutputVectorLayer(
        self.OUTPUT,
        self.tr('Output'),
        type = QgsProcessing.TypeVectorAnyGeometry)
)

Then, in your processAlgorithm method (simplified to just the relevant bits):

def processAlgorithm(self, parameters, context, feedback):
    crs = self.parameterAsCrs(parameters, self.CRS, context)
    inputFile = self.parameterAsFile(parameters, self.FILEIN, context)

    uri = ('file:///{}?'
           'type=regexp'
           '&delimiter={}'
           '&skipLines={}'
           '&useHeader=No'
           '&trimFields=Yes'
           '&xField={}'
           '&yField={}'
           '&crs={}'
           '&spatialIndex=Yes'
           '&subsetIndex=no'
           '&watchFile=Yes').format(inputFile,
                                    regex,
                                    skips,
                                    'Easting',
                                    'Northing',
                                    crs.geographicCrsAuthId())

    vl = QgsVectorLayer(uri, 'MY_LAYER', 'delimitedtext')

    return {self.OUTPUT: vl}
  • I have no doubt the answer is correct, although, interestingly, my script still get QGIS to crash every single time. I am loading a 46MB text file that contains a bit less than 582k points but memory shouldn't be a problem as a standalone script works fine every time. – YeO May 8 '18 at 11:57
  • I've currently resorted to parse the file manually and went back to the original template with a QgsProcessingParameterFeatureSink. This is actually cleaner as I am able to have proper names for Fields and icing on the cake, it's even a little faster than the delimitedtext provider... – YeO May 12 '18 at 13:23
  • 1
    Just a comment for anyone using this solution. inputFile needs to be specified as a QgsProcessingParameterFile parameter in initAlgorithm for this to work (e.g. self.addParameter(QgsProcessingParameterFile(self.FILEIN, self.tr('Input file'))). – rudivonstaden Jun 28 '18 at 8:41

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.