Estoy tratando de editar el valor de un atributo para cada característica en una capa usando un complemento QGIS Python. Descubrí que hacer esto fuera del modo de edición es mucho más lento que durante la edición (incluso incluyendo la confirmación de las ediciones). Vea el código a continuación (líneas intercambiables en el mismo punto en un bucle). La diferencia de velocidad para mi conjunto de datos de muestra es de 2 segundos (modo de edición) frente a 72 segundos (no en modo de edición).
Modificación de un atributo en modo edición:
layer.changeAttributeValue(feature.id(), 17, QtCore.QVariant(value))
Modificación de un atributo fuera del modo de edición:
layer.dataProvider().changeAttributeValues({ feature.id() : { 17 : QtCore.QVariant(value) } })
¿Es este un comportamiento esperado? No necesito que el usuario pueda deshacer los cambios, así que no creo que necesite usar el modo de edición.
Edición 1: vea el código completo a continuación con ambas versiones incluidas (pero comentadas):
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)
Ambos métodos producen el mismo resultado, pero la escritura a través del proveedor de datos lleva mucho más tiempo. La función clasifica la proximidad de las características del edificio a los campos cercanos (morado) utilizando buffers pre-creados (marrón-ish).