3

I'm trying to write a Python script with QGIS 3.4 but I have troubles when I want to change attributes values from a field.

With the code below, new values are calculated and the python console returns me True, but when I'm charging the layers in my QGIS Project, the attributes of all my features have a value = 0.000.

My Python code looks like:

champs = couche.fields()
nom_champs = [champ.name() for champ in champs]
feature=couche.getFeatures()
for elem in feature:
      elem.setAttribute('STD_2D', np.sqrt(elem[5]*elem[5]+elem[6]*elem[6]))
      elem.setAttribute('STD_3D', np.sqrt(elem[5]*elem[5]+elem[6]*elem[6]+ elem[7]*elem[7]))

      couche.changeAttributeValue(elem.id(), 11, elem.attributes()[11], skipDefaultValues=True)
      couche.changeAttributeValue(elem.id(), 12, elem.attributes()[12], skipDefaultValues=True)

      couche.dataProvider().updateExtents()

I think that they are not updated despite my command: couche.dataProvider().updateExtents(). Do I need the other command like this one? Is it a problem due to how I'm writing my script?

I tried to find help with subjects like this one but without success.

Edit : I tried to use 'couche.startEditing()' or 'couche.commitChanges()' but when I'm doing that, the attributes of the field I have to change take no values. Attributes cases are blank.

If It can help, here are previous lines of my code:

if couche.isEditable() == False : 
   couche.startEditing() 

res=couche.dataProvider().addAttributes([QgsField("STD_2D", QVariant.Double,len=5,prec=4), QgsField("STD_3D",QVariant.Double,len=5,prec=4)])
couche.updateFields()

Edit 2: For those who have the same probleme, I solved it by using the library "csv" with python, without PyGis. Then I import the new csv with PyGis in my current project.

import csv

entree = csv.reader(open("Export_QGIS_bon.csv","r"),delimiter=',')
sortie = csv.writer(open("Pour_shp.csv", "w"),delimiter=',')
row = next(entree)
row.insert(13,'STD_2D')
row.insert(14,'STD_3D')
sortie.writerow(row)
for row in entree:
   row.insert(13,round(float(np.sqrt(float(row[5])*float(row[5])+
   float(row[6])*float(row[6]))),3))
   row.insert(14,round(float(np.sqrt(float(row[5])*float(row[5])+
   float(row[6])*float(row[6])+float(row[7])*float(row[7]))),3))
   sortie.writerow(row)
7
  • Welcome to GIS SE ! Have you tried a couche.startEditing() and after modifications a couche.commitChanges() ? Apr 12, 2019 at 9:07
  • Thanks for your help :) Yes I did, but when I'm doing that, the attributes of the field I have to change take no values. Attributes cases are blank. If It can help, here are previous lines of my code: if couche.isEditable() == False : couche.startEditing() res=couche.dataProvider().addAttributes([QgsField("STD_2D", QVariant.Double,len=5,prec=4),QgsField("STD_3D",QVariant.Double,len=5,prec=4)]) couche.updateFields()
    – Arnaud
    Apr 12, 2019 at 9:09
  • Edit your post to insert code values, it will be more readable. Thanks. Apr 12, 2019 at 9:36
  • I was thinking that the 2 lines beginning with 'elem.setAttribute()' were defining the new 'value' of the 'field' 11 named "STD_2D" and the 'field' 12 named "STD_3D", and then the 2 orthers lines were here to modify the values by the value I defined previously. Maybe I did not understood everything and these 4 lines are contradicting each other ?
    – Arnaud
    Apr 12, 2019 at 9:51
  • In lines include changeAttribute method, you set value of the attribute to itself. So, the value in index 11 (and 12) doesn't changeç Did you notice? Apr 12, 2019 at 9:53

1 Answer 1

2

Try in that way:

import numpy as np

couche = iface.activeLayer()

# Add new fields
res = couche.dataProvider().addAttributes([QgsField("STD_2D", QVariant.Double,len=5,prec=4), QgsField("STD_3D", QVariant.Double,len=5,prec=4)])
couche.updateFields()

fields = couche.fields()
std_2d_index = fields.indexOf("STD_2D") # get index number of field named "STD_2D"
std_3d_index = fields.indexOf("STD_3D") # get index number of field named "STD_3D"

with edit(couche): # open an edit session for 'couche' layer
    for elem in couche.getFeatures():
          # calculate new values
          std_2d = np.sqrt(elem[5]*elem[5]+elem[6]*elem[6])
          std_3d = np.sqrt(elem[5]*elem[5]+elem[6]*elem[6]+elem[7]*elem[7])

          # add calculated values to the fields
          couche.changeAttributeValue(elem.id(), std_2d_index, std_2d, skipDefaultValues=True)
          couche.changeAttributeValue(elem.id(), std_3d_index, std_3d, skipDefaultValues=True)

In edit session, you don't need layer's dataprovider.

1
  • Tanks for this code :) Unfortunately, when I'm running the code it's look like I have the same mistake than before.. The 'values' for all my 'attributes' takes 0.000. I'm gonna try again, do you not think that after the code you gave me, I have to use a function to "regenerate" or "update" the layer ? It's seems that no because we are in 'edit' session as you said and as I read.
    – Arnaud
    Apr 15, 2019 at 7:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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