1 pièce(s) jointe(s)
Demande d'aide sur Python 2.7 pour QGIS / PyQGIS (MAJ Champ existant en fonction d'un autre)
Bonjour à Toutes et à Tous,
Je me permets de vous contacter pour une demande en Python PyQGIS :
Je cherche à mettre à jour, en Python 2.7 pour QGIS 2.18 Las Palmas, un champ existant ( "ETIQUETTE") d'une table attributaire en fonction d'un autre champ ("MODE_ADDUC"), c'est-à-dire l'équivalent d'un CASE WHEN .... THEN .... ELSE ..... END en langage SQL.
-----------------------------------------------------------------
J'ai testé le code suivant en utilisant une condition if .....elif .......else (au lieu du CASE WHEN du langage SQL) :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#TEST : mettre à jour un champ existant avec boucle
from PyQt4.QtCore import *
from qgis.core import *
vl = iface.activeLayer()
vl.startEditing()
#step 1
vl.updateFields()
idx = vl.dataProvider().fieldNameIndex( 'ETIQUETTE' )
adduc = vl.dataProvider().fieldNameIndex( 'MODE_ADDUC' )
#step 2
for f in vl.getFeatures():
if f[adduc] == 'AERIEN':
f[idx] = 'CIEL'
elif f[adduc] == 'FACADE':
f[idx] = 'MUR'
elif f[adduc] == 'SOUTERRAIN':
f[idx] = 'TERRE'
else:
f[idx] = 'RIEN'
vl.updateFeature( f )
vl.commitChanges() |
mais la console Python me retourne
Code:
1 2 3 4
|
Traceback (most recent call last):
File "<input>", line 2, in <module>
KeyError: '-1' |
Pouvez-vous m'aider ?
-----------------------------------------------------------------
Pour info :
Le même type de code fonctionne, mais sans la condition if .... elif .... else :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
#mettre à jour un champ existant
from PyQt4.QtCore import QVariant
from qgis.core import QgsField, QgsExpression, QgsFeature
vl = iface.activeLayer()
vl.startEditing()
#step 1
vl.updateFields()
idx = vl.fieldNameIndex( 'ETIQUETTE' )
#step 2
for f in vl.getFeatures():
f[idx] = 'ETIQPHIL'
vl.updateFeature( f )
vl.commitChanges() |
En pièce Jointe : le Shapefile zippé "test_adresses.zip" contenant les champs mentionnés dans mes précédents exemples.
En vous remerciant par avance,
Philippe Schitter
fieldNameIndex( 'MOD_ADDUC' ) corrigé OK + problème sur le bouclage ?
Citation:
Envoyé par
wiztricks
Salut,
-1 est la valeur retournée par .fieldNameIndex pour signaler qu'il ne trouve pas le champ recherché ('MODE_ADDUC').
- W
Bonjour Wiztricks/Modérateur,
Tout d'abord Merci pour votre réponse.
L'erreur est très bête de ma part, le champ est orthographié ('MOD_ADDUC') et non ('MODE_ADDUC').
Ensuite, dans la déclaration des champs, j'ai supprimé la fonction dataProvider() inutile ici et génératrice d'erreurs.
Extraits du code au niveau des deux corrections :
Avant :
Code:
1 2 3 4 5
|
#step 1
vl.updateFields()
idx = vl.dataProvider().fieldNameIndex( 'ETIQUETTE' )
adduc = vl.dataProvider().fieldNameIndex( 'MODE_ADDUC' ) |
Après :
Code:
1 2 3 4 5
|
#step 1
vl.updateFields()
idx = vl.fieldNameIndex( 'ETIQUETTE' )
adduc = vl.fieldNameIndex( 'MOD_ADDUC' ) |
Suite à à ces deux corrections (('MOD_ADDUC') bien orthographié et dataProvider() supprimé),
le code ne génère plus d'erreur dans l'interpréteur mais ne modifie pas le champ ('ETIQUETTE'); bref, il ne fait rien.
Le bouclage sur l'ensemble des objets ne se lance pas visiblement.
Rappel 1 : le shapefile zippé "test_adresses.zip" est en pièce jointe depuis ma 1ère publication.
Rappel 2 :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#TEST : mettre à jour un champ existant avec boucle
from PyQt4.QtCore import QVariant
from qgis.core import QgsField, QgsExpression, QgsFeature
vl = iface.activeLayer()
vl.startEditing()
#step 1
vl.updateFields()
idx = vl.fieldNameIndex( 'ETIQUETTE' )
adduc = vl.fieldNameIndex( 'MOD_ADDUC' )
#step 2
for f in vl.getFeatures():
if f[adduc] == 'AERIEN':
f[idx] = 'CIEL'
elif f[adduc] == 'FACADE':
f[idx] = 'MUR'
elif f[adduc] == 'SOUTERRAIN':
f[idx] = 'TERRE'
else:
f[idx] = 'RIEN'
vl.updateFeature( f )
vl.commitChanges() |
Par conséquent, et sans vouloir abuser de votre temps, avez-vous une piste de correction à me suggérer ?
En vous remerciant par avance,
Bien Cordialement,
Philippe Schitter
MERCI (1 indentation en trop) + une dernière question d'ordre général
Citation:
Envoyé par
wiztricks
Salut,
Relisez le dernier code que vous avez posté et regardez quand est effectué l'appel à vl.updateFeature( f ) (ou comparez ces lignes aux premiers codes que vous avez posté).
note: je ne connais pas pyqgis, je lis juste votre code.
- W
MERCI beaucoup Wiztricks !
Effectivement, une indentation en trop à l'issue de ma condition if ... elif ... else.
Le bon code est :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
#TEST : mettre à jour un champ existant avec boucle
from PyQt4.QtCore import QVariant
from qgis.core import QgsField, QgsExpression, QgsFeature
vl = iface.activeLayer()
vl.startEditing()
#step 1
vl.updateFields()
idx = vl.fieldNameIndex( 'ETIQUETTE' )
adduc = vl.fieldNameIndex( 'MOD_ADDUC' )
#step 2
for f in vl.getFeatures():
if f[adduc] == 'AERIEN':
f[idx] = 'CIEL'
elif f[adduc] == 'FACADE':
f[idx] = 'MUR'
elif f[adduc] == 'SOUTERRAIN':
f[idx] = 'TERRE'
else:
f[idx] = 'RIEN'
vl.updateFeature( f )
vl.commitChanges() |
Par ailleurs, se suis débutant en Python et j'apprends en autodidacte avec les tutos et forums.
Ma question d'ordre général : lorsqu'on souhaite réaliser une série d'actions successives, un petit peu comme dans un ETL de type modèle graphique QGIS ou FME,
doit-on lancer, en Python, une action par Classe/Classe d'objets ? ou Non ?
Par exemple, en VisualBasic (MapBasic pour MapInfo) : chaque action est intégrée dans une procédure "Sub"
(Sub Main; Sub "Extraire points d'une polyligne"; Sub "Mettre À Jour un champ existant de la Table Attributaire; ......).
MERCI beaucoup encore.
Bien Cordialement,
Philippe Schitter