0

I have a model that works well but I can't iterate with a batch process. Therefore, I would like to use a python script to iterate to avoid repetitive tasks.

I want iterate my model (that I have created in graphical modeler) and the iteration should create x layers for x cities instead of 1 layer for 1 city.

In this example the python script should iterate once for Bellinzona and once for Mendrisio and give two layers: one for Bellinzona, one for Mendrisio.

What I did? I took the script from history when my model ran successfully for Bellinzona (from the history of the processing algorithm dialog). Here you can see the script of the algorithm when run successfully for Bellinzona:

processing.run("model:Zone_geo_aut.amm", {'autoritamministrativaselezionata':' \"Aut_amm\"  =  \'BELLINZONA\' ','comuneselezionato':' \"nome_comune\"  =  \'BELLINZONA\' ','vettorecomuni':'dbname=\'condivisione\' host=postgis.ti.ch port=6400 sslmode=disable key=\'objectid\' srid=21781 type=MultiSurface checkPrimaryKeyUnicity=\'1\' table=\"pubb\".\"comuni_mu_poligoni\" (shape) sql=','vettorizones1s2s3':'C:/Users/T149323/Scaricati 08.07.2020/File_per_Simone/layers_QGIS/export_gespos_zone_geometrie riparate.shp|layername=export_gespos_zone_geometrie riparate','qgis:deleteduplicategeometries_1:Zone_excel':'memory:'})

You can see that the most important thing is BELLINZONA, because is the variable that have to change in the iteration. For example if instead of BELLINZONA I have had MENDRISIO as a result I have had another result representing MENDRISIO. My purpose is to change every time 'BELLINZONA' with the other cities (that are in an attribute table in an input layer of the model) during the iteration.

If I do this script:

aList = ('BELLINZONA','MENDRISIO')
anIterator = iter(aList)
for item in anIterator:
    print(item)

the result is:

BELLINZONA

MENDRISIO

so it should be enough to insert in the processing.run of the model the variable "item" that is the list of cities in aList and the iteration should run without problems. In fact, if I inserted in the processing run the variable item I should obtain once the first layer 'BELLINZONA' and the second and last layer 'MENDRISIO'. It is my wished result!

Based on the script above that works right I created the script that should integrate in the processing.run the list variable "item" giving the iteration with two results, namley a first vector layer BELLLINZONA and a second layer MENDRISIO:

import processing
aList = ('BELLINZONA','MENDRISIO')
anIterator = iter(aList)
i=1

for item in anIterator:
    processing.run("model:Zone_geo_aut.amm", {'autoritamministrativaselezionata':' \"Aut_amm\"  =  \'item\' ','comuneselezionato':' \"nome_comune\"  =  \'item\' ','vettorecomuni':'dbname=\'condivisione\' host=postgis.ti.ch port=6400 sslmode=disable key=\'objectid\' srid=21781 type=MultiSurface checkPrimaryKeyUnicity=\'1\' table=\"pubb\".\"comuni_mu_poligoni\" (shape) sql=','vettorizones1s2s3':'C:/Users/T149323/Scaricati 08.07.2020/File_per_Simone/layers_QGIS/export_gespos_zone_geometrie riparate.shp|layername=export_gespos_zone_geometrie riparate','qgis:deleteduplicategeometries_1:Zone_excel':"C:/Users/T149323/Scaricati 08.07.2020/File_per_Simone/gis_data/shapefile/test"+str(i)+".shp"})
    i+=1

This script creates two layers called test1 and test2. Good? Yes because there is no python error when it run, but the big problem is that they are empty! I don't understand why!

I have already created loop for iteration with number variable in Python for other QGIS algorithms or graphical modeler algorithms and all works right! I have the problem of the empty result in QGIS always (and ONLY) when the variable for the iteration is of type string like city or other names.

Could someone explain why I am not able to run loop in QGIS with string variables and someone could edit my last script code above?

3
  • I've added the [qgis] tag because its not in the title and you don't mention it until near the end - always a good idea to tag the software you are using. – Spacedman Jul 18 '20 at 13:55
  • Wherre do you add? I don't see the tag, I continue to see [model], [python],[iteration] at the end of my message, but not [QGIS] – simone100 Jul 19 '20 at 9:41
  • ugh, I've added it now! I think I got distracted writing the comment! – Spacedman Jul 19 '20 at 17:32
2

Try the following

aList = ('BELLINZONA','MENDRISIO') # Already iterable so your iter is not needed

for i, item in enumerate(aList): # enumerate is a way to get index + list element
    processing.run("model:Zone_geo_aut.amm", {
        'autoritamministrativaselezionata': ' \"Aut_amm\"  =  \'{}\' '.format(item),
        'comuneselezionato': ' \"nome_comune\"  =  \'{}\' '.format(item),
        'vettorecomuni': 'dbname=\'condivisione\' host=postgis.ti.ch port=6400 sslmode=disable key=\'objectid\' srid=21781 type=MultiSurface checkPrimaryKeyUnicity=\'1\' table=\"pubb\".\"comuni_mu_poligoni\" (shape) sql=',
        'vettorizones1s2s3': 'C:/Users/T149323/Scaricati 08.07.2020/File_per_Simone/layers_QGIS/export_gespos_zone_geometrie riparate.shp|layername=export_gespos_zone_geometrie riparate',
        'qgis:deleteduplicategeometries_1:Zone_excel': "C:/Users/T149323/Scaricati 08.07.2020/File_per_Simone/gis_data/shapefile/test{}.shp".format(str(i + 1))
    })

We use Python format here. You can look at https://pyformat.info to learn more about it. You also need to be aware of f-strings (https://realpython.com/python-f-strings/) as long your PyQGIS Python is 3.6+ (PS: last section of my answer is about honing Python skills, unrelated to geospatial part or QGIS)

2
  • Thank you, now it works! – simone100 Jul 20 '20 at 10:06
  • 1
    I think to have voted wrong. How can I change. Maybe I voted this answer is not useful. @BERA – simone100 Sep 8 '20 at 7:12

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.