I have two shapefiles (drenagem and rio_pri). I need to loop through every feature from rio_pri and save all those features from drenagem that intersect rio_pri. So I wrote the following code to be ran in Python Terminal. I'm using QGis 2.18.17 and Linux Mint 19.

import processing
drenagem = QgsVectorLayer('/home/tiago/Documentos/Rios_mata_disol.shp','Rios_mata_disol','ogr')
rio_pri = QgsVectorLayer('/home/tiago/Documentos/rios_linha_costa.shp','rios_linha_costa','ogr')
# Loop
for r in rio_pri.getFeatures():
    processing.runalg("qgis:selectbylocation", drenagem, r,['intersects'],0,0)
    r_cod = r['COCURSODAG']
    path = r_cod+'.shp'
    processing.runalg('qgis:saveselectedfeatures', drenagem, path)

Then for every feature from rio_pri I get this message at console.

Unable to execute algorithm
Wrong parameter value: <qgis._core.QgsFeature object at 0x7ffb6620b770>

I guess I should not use the r as an argument of qgis:selectbylocation, but I could not figure out what should I use instead.

  • Your main problem is that you are trying to run the processing algorithms for every feature in a layer! The algorithms themselves loop over the features. Just call select by location once, pass 'drenagem' as input and 'rio_pri' as intersect, then call save selected features on 'drenagem'. Check the docs: docs.qgis.org/2.18/en/docs/user_manual/processing_algs/qgis/… docs.qgis.org/2.8/en/docs/user_manual/processing_algs/qgis/… – Ben W Jun 6 at 22:51
  • @BenW But I don't want to select features from 'drenagem' that intersect 'rio_pri' just ONCE. I need to do the select by location feature by feature from 'rio_pri'. – tiago Jun 7 at 11:57
  • @smiler I check that before, but I could not adapt to my code. – tiago Jun 7 at 11:59
  • OK, I misunderstood your goal. Do you mean that you want to save a new shapefile for every feature in rio_pri containing just the intersecting features from drenagem? What are the geometry types of the layers? – Ben W Jun 7 at 12:55

Edit: After reading your subsequent comments above about what you are trying to achieve, I now doubt this actually what you want...

I have written the code below which you should be able to adapt. I have tested this in QGIS 3.4 and have included some commented lines which should allow for adaptation to QGIS 2.18. No guarantees though as I have not used the QGIS 2 API for a while now. If it's possible for you, I would recommend upgrading to at least QGIS 3.4. The script below assumes the 2 layers are loaded in the current project. My output files are in geopackage format, named 'test_file_' appended with the id of the intersecting feature to which they belong- you can change as required. Also, double backslashes in the output file path string works on Windows- I'm not sure about Linux.

I hope this helps.

import processing

rio_pri = QgsProject().instance().mapLayersByName('rios_linha_costa')[0]
#QGIS 2# rio_pri = QgsMapLayerRegistry().instance().mapLayersByName('rios_linha_costa')[0]
drenagem = QgsProject().instance().mapLayersByName('Rios_mata_disol')[0]
#QGIS 2# drenagem = QgsMapLayerRegistry().instance().mapLayersByName('Rios_mata_disol')[0]
index = QgsSpatialIndex(drenagem.getFeatures())
for feat in rio_pri.getFeatures():
    select_ids = []
    geoms = feat.geometry()
    engine = QgsGeometry.createGeometryEngine(geoms.constGet())
    intersection = index.intersects(geoms.boundingBox())
    candidates = drenagem.getFeatures(QgsFeatureRequest().setFilterFids(intersection))
    for f in candidates:
        if engine.intersects(f.geometry().constGet()):
    out_layer = 'Path\\To\\Output\\Location\\test_file_{}.gpkg'.format(str(feat.id()))
    # change extension to .shp if preferred
    processing.run('native:saveselectedfeatures', {'INPUT': drenagem,
    'OUTPUT': out_layer})
  • Thank you @Benw, I'll try it. – tiago Jun 9 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.