J'essaie de modifier la valeur d'un attribut pour chaque entité d'une couche à l'aide d'un plugin QGIS Python. J'ai trouvé que faire cela en dehors du mode d'édition est beaucoup plus lent que lors de l'édition (même en validant les modifications). Voir le code ci-dessous (lignes interchangeables au même point dans une boucle). La différence de vitesse pour mon échantillon de données est de 2 secondes (mode édition) contre 72 secondes (pas en mode édition).
Modification d'un attribut en mode édition:
layer.changeAttributeValue(feature.id(), 17, QtCore.QVariant(value))
Modification d'un attribut en dehors du mode d'édition:
layer.dataProvider().changeAttributeValues({ feature.id() : { 17 : QtCore.QVariant(value) } })
Est-ce un comportement attendu? Je n'ai pas besoin que l'utilisateur puisse annuler les modifications, donc je ne pense pas avoir besoin d'utiliser le mode d'édition.
Edit 1: Voir le code complet ci-dessous avec les deux versions incluses (mais commentées):
def run(self):
try:
# create spatial index of buffered layer
index = QgsSpatialIndex()
self.layer_buffered.select()
for feature in self.layer_buffered:
index.insertFeature(feature)
# enable editing
#was_editing = self.layer_target.isEditable()
#if was_editing is False:
# self.layer_target.startEditing()
# check intersections
self.layer_target.select()
self.feature_count = self.layer_target.featureCount()
for feature in self.layer_target:
distance_min = None
fids = index.intersects(feature.geometry().boundingBox())
for fid in fids:
# feature's bounding box and buffer bounding box intersect
feature_buffered = QgsFeature()
self.layer_buffered.featureAtId(fid, feature_buffered)
if feature.geometry().intersects(feature_buffered.geometry()):
# feature intersects buffer
attrs = feature_buffered.attributeMap()
distance = attrs[0].toPyObject()
if distance_min is None or distance < distance_min:
distance_min = distance
if self.abort is True: break
if self.abort is True: break
# update feature's distance attribute
self.layer_target.dataProvider().changeAttributeValues({feature.id(): {self.field_index: QtCore.QVariant(distance_min)}})
#self.layer_target.changeAttributeValue(feature.id(), self.field_index, QtCore.QVariant(distance_min))
self.calculate_progress()
# disable editing
#if was_editing is False:
# self.layer_target.commitChanges()
except:
import traceback
self.error.emit(traceback.format_exc())
self.progress.emit(100)
self.finished.emit(self.abort)
Les deux méthodes produisent le même résultat, mais l'écriture via le fournisseur de données prend beaucoup plus de temps. La fonction classe la proximité des caractéristiques du bâtiment aux champs voisins (violet) à l'aide de tampons pré-créés (brun-ish).