I'm trying to use QGIS to loop through a set of points, find their elevation from a DEM and use that value to update the point layer's attribute table. The loop works fine until I try to use changeAttributeValues(), and I can change the attribute values outside of the loop, but when I try to put the two together I cause a dump.
while provider.nextFeature(feat):
geom = feat.geometry()
x = geom.asPoint()
res, ident = rlayer.identify(QgsPoint(x))
for (k,v) in ident.iteritems():
elevation = float(v)
attrs = { 2 : elevation }
caps = vlayer.dataProvider().capabilities()
if caps & QgsVectorDataProvider.ChangeAttributeValues:
vlayer.dataProvider().changeAttributeValues({ fid : attrs })
This causes the following error in Linux:
*** glibc detected *** python2: free(): invalid pointer: 0x00000000024655b8 ***
Edit:
The problem isn't the loop, it is now I'm calling changeAttributeValues(). I've simplified the script down to just update a single point and it causes the same core dump. Here's the updated script:
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from qgis.core import *
import qgis.utils
#initializes QGIS and points python to where it can find QGIS's stuff
QgsApplication.setPrefixPath("/usr/", True)
QgsApplication.initQgis()
vlayer = QgsVectorLayer("/gis/vector/elev_pts.shp", "elev_pts", "ogr")
if not vlayer.isValid():
print "Layer did not load!"
vlayer.dataProvider().changeAttributeValues({ 0: 2: 432.1 })
QgsApplication.exitQgis()
2 Answers 2
Figured it out, by using changeAttributeValue() instead of changeAttributeValues() I got the script to work. Here's a loop that works:
# Loop through each point feature
while provider.nextFeature(feat):
geom = feat.geometry()
x = geom.asPoint()
#Get the raster value of the cell under the vector point
res, ident = rlayer.identify(QgsPoint(x))
#The key is the raster band, and the value is the cell's raster value
for (k,v) in ident.iteritems():
elevation = float(v)
fid = int(feat.id())
vlayer.startEditing()
vlayer.changeAttributeValue(fid, 2, elevation)
vlayer.commitChanges()
This only works if the raster is a single band raster.
What I see from your code: attrs
is a dict
that always has the key 2
. When you use changeAttributeValues
you also pass a dict to the function (which might be correct but is very unusual). But
({ fid : attrs }) equals ({ fid : { 2 : elevation }})
Is this maybe causing the problem?
-
I was working off of an example from the pyqgis cookbook and they show to use a dict as the second parameter. The 2 in this case is the index for the field to be modified and the second element, in this case the value of elevation, is the new value for that field. Fid here is the feature ID for the feature getting the new value.HeyOverThere– HeyOverThere2012年10月03日 12:45:01 +00:00Commented Oct 3, 2012 at 12:45
-
So if you hard code the call, e.g.
vlayer.dataProvider().changeAttributeValues({ fid : {2: 4.0}})
it works? And what doesfid = feat.id()
return by the way?LarsVegas– LarsVegas2012年10月03日 13:19:01 +00:00Commented Oct 3, 2012 at 13:19 -
Yeah, I just tried it in the Python console and it updated the correct record with the correct value. fid = feat.id() returned type long, changed it to fid = int(feat.id()) and it still core dumps.HeyOverThere– HeyOverThere2012年10月03日 13:31:31 +00:00Commented Oct 3, 2012 at 13:31
if
meant to be inside thefor
?