How to Use `layer.getFeatures()` in a Standalone Script – Best Practices

pyqgisqgis-processingstandalone

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 + "\Desktop\Test\\"
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 + "\Desktop\Test\\"
    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)
    

Best Answer

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.