Sunday, 26 April 2015

How to change attributes with QGIS Python?


I have this piece of code which I would like to use for inserting values into a column. It does not throw an error, the changes are not written to the source (shapefile).


from qgis.utils import iface
from PyQt4.QtCore import *

layers = iface.legendInterface().layers()

for layer in layers:
name = layer.name()
if name.endswith('x'):

provider = layer.dataProvider()
features = provider.getFeatures()
for feature in features:
feature.setAttribute('attr', 'a')

I understood there are two ways of editing data sources: directly with dataProvider or with edit buffer. If I got it right, it shouldn't be necessary to call commit action when using dataProvider.


I'm using QGIS 2.2 Valmiera.



Answer



You are right, that you don't need to call commit if you work on the dataProvider directly. However, this will also commit every update immediately, leading to more I/O overhead (often decreased performance) and poor transaction handling. This is to say, the method works, but use it carefully. I have added another method below which is better suited in most cases.


The problem in the code is, that you are only setting the attribute on the feature in memory and don't tell the provider, that this feature changed. Instead, try the following code. It buffers all updates in the updateMap and then executes it in one go at the end, therefore allowing batch updates (useful e.g. on slow networks). Another possibility would be to issue updateAttributeValue directly in the loop.



from qgis.utils import iface
from PyQt4.QtCore import *

layers = iface.legendInterface().layers()

for layer in layers:
name = layer.name()
if name.endswith('x'):
provider = layer.dataProvider()
updateMap = {}

fieldIdx = provider.fields().indexFromName( 'attr' )
features = provider.getFeatures()
for feature in features:
updateMap[feature.id()] = { fieldIdx: 'a' }

provider.changeAttributeValues( updateMap )

The generally recommended way:


with edit(layer):
for feature in layer.getFeatures():

feature['fieldName'] = newValue
layer.updateFeature(feature)

http://qgis.org/api/2.2/classQgsVectorDataProvider.html#a99a5d01c33c1cadb7ae9209b68cd8743


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...