TransWikia.com

How to use `layer.getFeatures()` in a standalone script?

Geographic Information Systems Asked on July 13, 2021

I am following the QGIS Cookbook and this post where it concerns reading attributes from layers. I would like to exploit this method and implement it into a standalone script.

Essentially, I want to read the first feature of a shapefile from a field called Rank, take the value of this feature (all values in the Rank field are the exact same) and include it into a QGIS algorithm.

I wonder if there’s an alternative to using layer.getFeatures() as, I believe, this is used with the canvas when QGIS is running. I have the following basic script but doesn’t like fname.getFeatures():

path_dir = home + "DesktopTest"
path_res = path_dir + "Results"

for fname in glob.glob(path_dir + "*.shp"):
    for feature in fname.getFeatures():
        fid = 1
        iterator = fname.getFeatures(QgsFeatureRequest().setFilterFid(fid))
        idx = fname.fieldNameIndex('Rank')
        Rank_value = idx[1]

        #Do some processing, finish with field calculator algorithm

        general.runalg("qgis:fieldcalculator", fname, 'Rank', 1, 10, 0, False, Rank_value, path_res + fname)

Is this the correct method or would it be much easier to read the Rank_value from a shapefile and write to another programatically?


EDIT:

Following @gcarrillo’s answer, the script does not produce any results. I have modified the script to match the one suggested but not sure why no output files are produced.

To try and clarify exactly what I’m looking for:

  1. A value from the Rank field of a shapefile is read.
  2. A grid is created.
  3. The same shapefile is clipped onto the grid (it would then have more polygons, thus more features).
  4. The Rank field for this newly clipped shapefile is updated with the value read at the start.
  5. Next shapefile…

    path_dir = home + "DesktopTest"
    path_res = path_dir + "Results"
    
    for fname in glob.glob(path_dir + "*.shp"):
        vLayer = QgsVectorLayer(fname,"any name","ogr")
        idx = fname.fieldNameIndex('Rank')
        Rank_value = vLayer.uniqueValues(idx)[0]
    
        outputs_1=general.runalg("qgis:creategrid", 1000, 1000, 24108, 18351.157175, 258293.802316, 665638.226408, 1, 'EPSG:7405', None)
        outputs_2=general.runalg("qgis:clip", outputs_1['SAVENAME'], fname, None)
        outputs_3=general.runalg("qgis:fieldcalculator", outputs_2, 'Rank', 1, 10, 0, False, Rank_value, path_res + fname)
    

2 Answers

I've tested the following script on GNU/Linux, QGIS v.2.8.1, Processing v.2.6 and Processing v.2.9.1.

import sys,os,glob
from qgis.core import *
from PyQt4.QtGui import *

app = QApplication([])
QgsApplication.setPrefixPath("/usr", True) # Adjust it to your path
QgsApplication.initQgis()

path_dir = "/docs/borrar/test/"
path_res = path_dir + "results/"

sys.path.append("/usr/share/qgis/python/plugins/") # Where Processing is installed
from processing.core.Processing import Processing
Processing.initialize()
from processing.tools import *

for fname in glob.glob(path_dir + "*.shp"):
    vLayer = QgsVectorLayer(fname,"any name","ogr")
    idx = vLayer.fieldNameIndex('rank')
    Rank_value = vLayer.uniqueValues(idx)[0] # uV returns a list, get the 1st element

    #Do some processing, finish with field calculator algorithm
    outputs_1=general.runalg("qgis:creategrid",1,"-956314.538361,3285493.72235,-53712.3143749,1885220.75154",250000,250000,None)
    outputs_2=general.runalg("qgis:clip", outputs_1['OUTPUT'], fname, None)
    general.runalg("qgis:advancedpythonfieldcalculator", outputs_2['OUTPUT'], 'rank', 1, 10, 3, False, "value=%f" % Rank_value, path_res + os.path.basename(fname))

QgsApplication.exitQgis()

As you can see, the syntax of the qgis:creategrid algorithm differs from your version and from the version we ran at Import error for qgis.core when running OSGeo4w shell script. Additionally, I ended up using the qgis:advancedpythonfieldcalculator algorithm, which provides a help.

Hope you can make it to work in your environment, pay attention to paths.

Correct answer by Germán Carrillo on July 13, 2021

For the first question:

You need to create a QgsVectorLayer object from your Shapefile path. Only then you can access the getFeatures() function. That is:

for fname in glob.glob(path_dir + "*.shp"):
    for feature in QgsVectorLayer(fname,"any name","ogr").getFeatures():

My recommended way of doing it

You don't actually need to access getFeatures() nor to use a for. You can accomplish what you want with this code:

path_dir = home + "DesktopTest"
path_res = path_dir + "Results"

for fname in glob.glob(path_dir + "*.shp"):
    vLayer = QgsVectorLayer(fname,"any name","ogr")
    idx = vLayer.fieldNameIndex('Rank')
    Rank_value = vLayer.uniqueValues(idx)[0] # uV returns a list, get the 1st element

    #Do some processing, finish with field calculator algorithm
    general.runalg("qgis:fieldcalculator", fname, 'Rank', 1, 10, 0, False, Rank_value, path_res + os.path.basename(fname))

Since you'll be using QgsVectorLayer, don't forget to set the prefix path before initializing QGIS, as you did at Getting random values from geometryType() in a standalone PyQGIS script.

Answered by Germán Carrillo on July 13, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP