0

I am trying to calculate a new field in an attribute table using a QGIS expression in PyQGIS, and per the recommendations found here, I'm using the with edit(): method. However, it is causing various troubles. For a start, this codeblock taken from the link above returns syntax error for print repr(err).

try:
    with edit(layer):
        layer.addFeature(...)
        layer.updateFeatures(...)
except QgsEditException as err:
    print repr(err)

yields ↓

    print repr(err)
          ^
SyntaxError: invalid syntax

print(repr(err)) doesn't return any error though, but now there's another problem. The script disappears from the Processing toolbox if I import QgsEditException. This is how the top of my script looks:

from qgis.PyQt.QtCore import *
from qgis.core import (QgsProcessing,
                       QgsProcessingException,
                       QgsProcessingAlgorithm,
                       QgsProcessingParameterFeatureSource,
                       QgsProcessingParameterFeatureSink,
                       QgsProcessingParameterField,
                       QgsField,
                       QgsGeometry,
                       QgsExpression,
                       edit,
                       QgsEditException)
from qgis import processing

I can solve that by not using QgsEditException. So I remove it from the imports, and I remove the try...except... statement in the codeblock and just stick with the with edit(): unconditionally. But then the script crashes when I run it instead. I don't even get en error message, it just freezes and I have to force quit QGIS.

I am a mere beginner and this exceeds my understanding. Why is with edit() not working, an what should I do?

7
  • 1
    Is there really a ´QgsEditException` in existance? Jan 15, 2023 at 18:32
  • 4
    @joel, the post was 7.5 years ago, which is a very long time for actively developed software. QGIS was in the 2.x days when the post was written, and QGIS switched to Python 3 with QGIS 3, which is why the print statement gives an error because it is Python 2 syntax. In terms of QgsEditException, I don't believe it ever existed, and the post author probably meant to write QgsEditError but didn't try his own code to catch the mistake.
    – bixb0012
    Jan 15, 2023 at 19:47
  • 4
    Furthermore, .updateFeatures() is not a method of QgsVectorLayer. It's worth mentioning that the existing updateFeature method is not used in this context either (it is to overwrite the geometry and attributes of an exiting feature).
    – Matt
    Jan 15, 2023 at 21:04
  • 1
    @bixb0012: Thank you for the info. I'm a Python beginner, couldn't have guessed this myself, I just trusted posts from the OpenGIS company to be accurate and correct. Problem solved with print(repr(err)) and QgsEditError instead of QgsEditException. Thanks also @Matt for the heads-up, I won't be using updateFeature at all in this context.
    – Joel
    Jan 16, 2023 at 9:05
  • 1
    OPENGIS are highly competent and respectable QGIS developers, the issue is that the post in question was very old and for a very different QGIS version :) Jan 16, 2023 at 10:23

1 Answer 1

4

As @bixb0012 pointed out, the problem was that QgsEditException doesn't exist, but it should be QgsEditError, and that print repr(err) is old Python 2.x syntax, not supported in QGIS3 anymore, that's why it should be print(repr(err)). In addition, as @Matt pointed out updateFeatures() is also not supported anymore in the way that it's used in the code block above, because it's not a method of QgsVectorLayer. So a result that does in fact work would be for example this:

from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsField,
                       QgsExpression,
                       QgsExpressionContext,
                       QgsExpressionContextUtils,
                       edit,
                       QgsEditError)

expression = QgsExpression('exampleexpression')
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(layer))
try:
    with edit(layer):
        layer.dataProvider().addAttributes([QgsField('new_fieldname', QVariant.Double)])
        layer.updateFields()
        for f in layer.getFeatures():
            context.setFeature(f)
            f['new_fieldname'] = expression.evaluate(context)
            layer.updateFeature(f)
except QgsEditError as err:
    print(repr(err))

Why my script crashed before was probably because of some other unforeseen blunder, but with this code, it works for me at least.

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.