Le fragment de code sur cette page nécessite les importations suivantes:
from qgis.core import (
edit,
QgsExpression,
QgsExpressionContext,
QgsFeature,
QgsFeatureRequest,
QgsField,
QgsFields,
QgsVectorLayer,
QgsPointXY,
QgsGeometry,
QgsProject,
QgsExpressionContextUtils
)
Expressions, Filtrage et Calcul de valeurs¶
QGIS propose quelques fonctionnalités pour faire de l’analyse syntaxique d’expressions semblable au SQL. Seulement un petit sous-ensemble des syntaxes SQL est géré. Les expressions peuvent être évaluées comme des prédicats booléens (retournant Vrai ou Faux) ou comme des fonctions (retournant une valeur scalaire). Voir Expressions dans le manuel Utilisateur pour une liste complète des fonctions disponibles.
Trois types basiques sont supportés :
nombre — aussi bien les nombres entiers que décimaux, par exemple
123
,3.14
texte — ils doivent être entre guillemets simples:
'hello world'
référence de colonne — lors de l’évaluation, la référence est remplacée par la valeur réelle du champ. Les noms ne sont pas échappés.
Les opérations suivantes sont disponibles:
opérateurs arithmétiques:
+
,-
,*
,/
,^
parenthèses: pour faire respecter la précédence des opérateurs:
(1 + 1) * 3
les unaires plus et moins:
-12
,+5
fonctions mathématiques:
sqrt
,sin
,cos
,tan
,asin
,acos
,atan
fonctions de conversion :
to_int
,to_real
,to_string
,to_date
fonctions géométriques:
$area
,$length
Fonctions de manipulation de géométries :
$x
,$y
,$geometry
,num_geometries
,centroid
Et les prédicats suivants sont pris en charge:
comparaison:
=
,!=
,>
,>=
,<
,<=
comparaison partielle:
LIKE
(avec % ou _),~
(expressions régulières)prédicats logiques:
AND
,OR
,NOT
Vérification de la valeur NULL:
IS NULL
,IS NOT NULL
Exemples de prédicats:
1 + 2 = 3
sin(angle) > 0
'Hello' LIKE 'He%'
(x > 10 AND y > 10) OR z = 0
Exemples d’expressions scalaires:
2 ^ 10
sqrt(val)
$length + 1
Analyse syntaxique d’expressions¶
The following example shows how to check if a given expression can be parsed correctly:
exp = QgsExpression('1 + 1 = 2')
assert(not exp.hasParserError())
exp = QgsExpression('1 + 1 = ')
assert(exp.hasParserError())
assert(exp.parserErrorString() == '\nsyntax error, unexpected $end')
Évaluation des expressions¶
Expressions can be used in different contexts, for example to filter features or to compute new field values. In any case, the expression has to be evaluated. That means that its value is computed by performing the specified computational steps, which can range from simple arithmetic to aggregate expressions.
Expressions basiques¶
Cette expression basique est évaluée à 1, signifiant « vrai »:
exp = QgsExpression('1 + 1 = 2')
assert(exp.evaluate())
Expressions avec entités¶
To evaluate an expression against a feature, a QgsExpressionContext
object has to be created and passed to the evaluate function in order to allow the expression to access
the feature’s field values.
The following example shows how to create a feature with a field called « Column » and how to add this feature to the expression context.
fields = QgsFields()
field = QgsField('Column')
fields.append(field)
feature = QgsFeature()
feature.setFields(fields)
feature.setAttribute(0, 99)
exp = QgsExpression('"Column"')
context = QgsExpressionContext()
context.setFeature(feature)
assert(exp.evaluate(context) == 99)
The following is a more complete example of how to use expressions in the context of a vector layer, in order to compute new field values:
from qgis.PyQt.QtCore import QVariant
# create a vector layer
vl = QgsVectorLayer("Point", "Companies", "memory")
pr = vl.dataProvider()
pr.addAttributes([QgsField("Name", QVariant.String),
QgsField("Employees", QVariant.Int),
QgsField("Revenue", QVariant.Double),
QgsField("Rev. per employee", QVariant.Double),
QgsField("Sum", QVariant.Double),
QgsField("Fun", QVariant.Double)])
vl.updateFields()
# add data to the first three fields
my_data = [
{'x': 0, 'y': 0, 'name': 'ABC', 'emp': 10, 'rev': 100.1},
{'x': 1, 'y': 1, 'name': 'DEF', 'emp': 2, 'rev': 50.5},
{'x': 5, 'y': 5, 'name': 'GHI', 'emp': 100, 'rev': 725.9}]
for rec in my_data:
f = QgsFeature()
pt = QgsPointXY(rec['x'], rec['y'])
f.setGeometry(QgsGeometry.fromPointXY(pt))
f.setAttributes([rec['name'], rec['emp'], rec['rev']])
pr.addFeature(f)
vl.updateExtents()
QgsProject.instance().addMapLayer(vl)
# The first expression computes the revenue per employee.
# The second one computes the sum of all revenue values in the layer.
# The final third expression doesn’t really make sense but illustrates
# the fact that we can use a wide range of expression functions, such
# as area and buffer in our expressions:
expression1 = QgsExpression('"Revenue"/"Employees"')
expression2 = QgsExpression('sum("Revenue")')
expression3 = QgsExpression('area(buffer($geometry,"Employees"))')
# QgsExpressionContextUtils.globalProjectLayerScopes() is a convenience
# function that adds the global, project, and layer scopes all at once.
# Alternatively, those scopes can also be added manually. In any case,
# it is important to always go from “most generic” to “most specific”
# scope, i.e. from global to project to layer
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(vl))
with edit(vl):
for f in vl.getFeatures():
context.setFeature(f)
f['Rev. per employee'] = expression1.evaluate(context)
f['Sum'] = expression2.evaluate(context)
f['Fun'] = expression3.evaluate(context)
vl.updateFeature(f)
print( f['Sum'])
Filtrer une couche à l’aide d’expressions¶
L’exemple suivant peut être utilisé pour filtrer une couche et ne renverra que les entités qui correspondent au prédicat.
layer = QgsVectorLayer("Point?field=Test:integer",
"addfeat", "memory")
layer.startEditing()
for i in range(10):
feature = QgsFeature()
feature.setAttributes([i])
assert(layer.addFeature(feature))
layer.commitChanges()
expression = 'Test >= 3'
request = QgsFeatureRequest().setFilterExpression(expression)
matches = 0
for f in layer.getFeatures(request):
matches += 1
assert(matches == 7)
Gestion des erreurs dans une expression¶
Les erreurs liées à une expression peuvent se révéler lors de l’analyse de l’expression ou de son évaluation :
exp = QgsExpression("1 + 1 = 2")
if exp.hasParserError():
raise Exception(exp.parserErrorString())
value = exp.evaluate()
if exp.hasEvalError():
raise ValueError(exp.evalErrorString())