1

I am very new to QGIS3 and I am currently trying to convert a python script from QGIS 2.18 to QGIS 3. Therefore, I am trying to integrate my python script into the template from underdark -> see here

I am currently stepping from one error into another so I seek help as I was not able to find any other question on Stack Exchange or any documentation.

Here is some part of my script so far:

def processAlgorithm(self, parameters, context, feedback):
    inEdges = self.parameterAsVectorLayer(parameters, self.INPUT_VECTOR_LAYER_EDGES, context)
    inNodes = self.parameterAsVectorLayer(parameters, self.INPUT_VECTOR_LAYER_NODES, context)
    outMerged = self.parameterAsOutputLayer(parameters, self.OUTPUT_VECTOR_LAYER_MERGED, context)

    #DO SOME CALCULATION

    # get field indices for inputlayer
    idxEdgeId = inEdges.fieldNameIndex(ID)
    idxPriority = inEdges.fieldNameIndex(PRIORITY)
    idxLength  = inEdges.fieldNameIndex(LENGTH)
    idxTime    = inEdges.fieldNameIndex(TIME)
    idxFrom  = inEdges.fieldNameIndex(FROM)
    idxTo  = inEdges.fieldNameIndex(TO)

    idx_id = inNodes.fieldNameIndex(NODEID)
    idx_x = inNodes.fieldNameIndex(COORD_X)
    idx_y = inNodes.fieldNameIndex(COORD_Y)

    # Set the provider to accept the data source
    outdp = outMerged.dataProvider()

    # define attributes and add them to the vector layer
    outdp.addAttributes([QgsField(EDGEID, QVariant.String),
                        QgsField(NODE1, QVariant.String),
                        QgsField(NODE2, QVariant.String),
                        QgsField(PRIORITY, QVariant.Int),
                        QgsField(VTO, QVariant.Double),
                        QgsField(VFROM, QVariant.Double)])
    outMerged.updateFields()

    # get field indices for outputlayer
    outEdgeId = outdp.fieldNameIndex(EDGEID)
    outNode1 = outdp.fieldNameIndex(NODE1)
    outNode2 = outdp.fieldNameIndex(NODE2)
    outPriority = outdp.fieldNameIndex(PRIORITY)
    outVTo = outdp.fieldNameIndex(VTO)
    outVFrom = outdp.fieldNameIndex(VFROM)

    listOfEdgeIds = []
    count = 0
    flag = 0

    (...)

For your information: I have 2 input vector layers (one point, and one line layer) and out of that, I want to create one outputlayer (which should be a line-vector layer as well).

But currently I have trouble with the "fieldNameIndex(QString)" - method in the first section of the code. I have already tried to call the method with the dataProvider() of the input layer, but that hasn't worked out. I get error:

Traceback (most recent call last): File "C:\Users\tlichten\AppData\Roaming\QGIS\QGIS3\profiles\default\processing\scripts\merging.py", line 89, in processAlgorithm idxEdgeId = inEdges.fieldNameIndex(ID) AttributeError: 'NoneType' object has no attribute 'fieldNameIndex'

Although I have to input vector layers, I cannot select any of them if I want to start the script. The execute script window looks like this:

enter image description here

In QGIS2.18, there would be two drop-down menus in which to choose between the input layeres.

I have adapted the initAlgorithm() to the following:

    def initAlgorithm(self, config=None):
    self.addParameter(QgsProcessingParameterVectorLayer(
        self.INPUT_VECTOR_LAYER_EDGES, 
        self.tr('Edges'),
        [QgsProcessing.TypeVectorAnyGeometry]))
    self.addParameter(QgsProcessingParameterRasterLayer(
        self.INPUT_VECTOR_LAYER_NODES,
        self.tr('Nodes')
        [QgsProcessing.TypeVectorAnyGeometry]))
    self.addParameter(QgsProcessingParameterRasterDestination(
        self.OUTPUT_VECTOR_LAYER_MERGED,
        self.tr("Output Vector Layer Merged"),
        [QgsProcessing.TypeVectorAnyGeometry]))

But I can still not select any input layers if I execute the script.

  • I have shortened the code segment. The error message I receive when trying to execute the script is as follows: Traceback (most recent call last): File "C:\Users\tlichten\AppData\Roaming\QGIS\QGIS3\profiles\default\processing\scripts\merging.py", line 89, in processAlgorithm idxEdgeId = inEdges.fieldNameIndex(ID) AttributeError: 'NoneType' object has no attribute 'fieldNameIndex' – applebrown Nov 26 '18 at 13:11
  • I have edited my question. Please see above. How do I select the layer in the input field. If I run the script from the toolbox I cannot select any inputlayer as it was with QGIS 2.18. I can just press start... – applebrown Nov 26 '18 at 13:45
  • Your code snippet is different than the sourced example you reference. That one uses a class which gets the parameters. – artwork21 Nov 26 '18 at 14:03
  • in initAlgorithm() function – artwork21 Nov 26 '18 at 14:41
  • 1
    You can't mix "Raster" and "Vector" in one parameter definition (your INPUT_VECTOR_LAYER_NODES name suggest it should be a vector not a raster) . Do you need Raster input or output? For output you should call self.addOutput. – barteksch Nov 26 '18 at 15:12
1

That method has been deprecated, use this instead to get the field index:

fields = inEdges.fields()
idxEdgeId = fields.indexFromName('fieldName')
  • thank you for your answer, I have tried your solution, but it looks like the fields() method is not known. This is my error now: Traceback (most recent call last): File "C:\Users\tlichten\AppData\Roaming\QGIS\QGIS3\profiles\default\processing\scripts\merging.py", line 89, in processAlgorithm fields = inEdges.fields() AttributeError: 'NoneType' object has no attribute 'fields' – applebrown Nov 26 '18 at 13:30
  • How/where is the processAlgorithm() being called? The vector layer "inEdges" is not valid. – artwork21 Nov 26 '18 at 13:38
  • I have edited the question. Please have a look! Thank you so much – applebrown Nov 26 '18 at 14:24
  • is the newFeature.setAttribute() method deprecated as well?? How can I set an attribute of a new feature for the output layer? – applebrown Nov 26 '18 at 15:40
  • 1
    That method should still work. The referenced blog you noted in your question shows how to do that. Also, that question is different from this question so you should post a new question about that. – artwork21 Nov 26 '18 at 17:09
2

fieldNameIndex function was removed in QGIS3:

Removed fieldNameIndex(), use fields().lookupField() or fields().indexFromName() instead

You can convert your code as follows:

inEdges = self.parameterAsVectorLayer(parameters, self.INPUT_VECTOR_LAYER_EDGES, context)
inEdgesFields = inEdges.fields()

idxEdgeId = inEdgesFields.indexFromName(ID)

For more details see https://qgis.org/api/api_break.html


Exception you've got, suggest that you have problem with parameters, make sure you add parameters with proper key in initAlgorithm function (in QGIS2 it was defineCharacteristics):

def initAlgorithm(self, config=None):
    self.addParameter(QgsProcessingParameterVectorLayer(self.INPUT_VECTOR_LAYER_EDGES, self.tr('Edges'), types=[QgsProcessing.TypeVector]))
  • thank you for your answer, I have tried your solution, but it looks like the fields() method is not known. This is my error now: Traceback (most recent call last): File "C:\Users\tlichten\AppData\Roaming\QGIS\QGIS3\profiles\default\processing\scripts\merging.py", line 90, in processAlgorithm inEdgesFields = inEdges.fields() AttributeError: 'NoneType' object has no attribute 'fields' – applebrown Nov 26 '18 at 13:31
  • Make sure the parameters are properly added in initAlgorithm(self, config=None) function and you select valid layer in the input field – barteksch Nov 26 '18 at 13:39
  • the initAlgorithm method should work properly. But how do I select the layer in the input field. If I run the script from the toolbox I cannot select any inputlayer as it was with QGIS 2.18. I can just press start... – applebrown Nov 26 '18 at 13:42
  • I have edited my question. Please have a look for better understanding :) – applebrown Nov 26 '18 at 13:46
  • See my edited answer – barteksch Nov 26 '18 at 13:48

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.