6

This question is very related to the unanswered Retrieve features from QgsFieldExpressionWidget pyqgis

I have a layer and I've build a QgsExpression that involves a field of that layer. What I'm trying to do is to evaluate the expression and get the results as a single list.

The problem is that I'm trying to do this with QGIS master (so the future 3 version) and the instruction of the PyQGIS cookbook are outdated because some API are changed.

Just to have an example:

vl = iface.activeLayer()
exp = QgsExpression('PH > 7') # where PH is the name of a field
exp.prepare(vl.pendingFields())


# then I get this error

Traceback (most recent call last):
  File "/usr/lib/python3.5/code.py", line 91, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
TypeError: QgsExpression.prepare(): argument 1 has unexpected type 'QgsFields'

Someone has already successfully used the QgsExpression for QGIS master?

1

3 Answers 3

3

I used your code in my QGIS Python Console (with a shapefile with 'PH' field; only one value > 7) and I got a result (see next image).

enter image description here

So, I printed 'vl.pendingFields()' to find out what kind of object is:

>>>vl.pendingFields()
<qgis._core.QgsFields object at 0x17E10E40>

and afterward, a help for QgsExpression.prepare for corroborating wich parameters it uses:

help(QgsExpression.prepare)
Help on built-in function prepare:

prepare(...)
    QgsExpression.prepare(QgsFields) -> bool
    QgsExpression.prepare(QgsExpressionContext) -> bool

In my case, used parameter is correct and the result was as expected. So, I suggest that you use 'help' command with your QGIS future 3 version to find out the new kind of parameters to use.

1
  • HI. thanks for the answer. I think that the use of prepare is deprecated in QGIS 3. The help function return my: prepare(...) Get the expression ready for evaluation - find out column indexes. \param context context for preparing expression .. versionadded:: 2.12 :rtype: bool
    – matteo
    Commented Jun 15, 2017 at 13:08
3

In QGIS 3.0, you may need to use a combination of the QgsExpressionContext and QgsExpressionContextScope classes:

vl = iface.activeLayer()
features = [feat for feat in vl.getFeatures()]

context = QgsExpressionContext()
scope = QgsExpressionContextScope()
context.appendScope(scope)
listOfResults = []

for feat in features:
    scope.setFeature(feat)
    exp = QgsExpression('PH > 7')
    listOfResults.append(exp.evaluate(context))

The output is boolean, either 0 (false) or 1 (true), and stored in a list:

>>> [0, 0, 0, 1, 1, 1]
1
  • 2
    context.appendScope(scope) line should be moved outside of the loop. Otherwise QGIS crashes. Commented Oct 14, 2018 at 18:54
2
    for name, layer in layers.iteritems():
        if(layer.name()=="[layer name]"):

            lay=layer

    expr = QgsExpression("\"REFCAT\"=22162C50309009")

    expr = QgsExpression(expresion)
    selection= lay.getFeatures(QgsFeatureRequest(expr))
    ids = [s.id() for s in selection]
    lay.setSelectedFeatures(ids)
    iface.legendInterface().setCurrentLayer(lay)
    iface.mapCanvas().zoomToSelected()

Is a code used by me, try changing the format of the expression with double quotation marks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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