QGIS 2.16: processing.runalg fails when run outside of QGIS in a custom application
The Processing error was fixed recently, see https://github.com/qgis/QGIS/commit/df2ca2e60798315d816966f25aa024b93835f776
Barry, thank you for your advice. Apparently, the QGIS core team changed the code. In QGIS 2.14 runalg
was defined as follows:
def runalg(alg, progress=None):
"""Executes a given algorithm, showing its progress in the
progress object passed along.
Return true if everything went OK, false if the algorithm
could not be completed.
"""
if progress is None:
progress = SilentProgress()
try:
alg.execute(progress)
return True
except GeoAlgorithmExecutionException as e:
ProcessingLog.addToLog(sys.exc_info()[0], ProcessingLog.LOG_ERROR)
progress.error(e.msg)
return False
So if progress is equal to None
(which is the case in my example code), SilentProgress
took care of it. By contrast, in QGIS 2.16 the corresponding if-statement was removed (see Barry's answer above), which leads to the failure of runalg
. One solution would be to manually edit the AlgorithmExecutor.py script by adding again the missing lines. In this case, one would have to add another import line to the beginning of the script (from processing.core.SilentProgress import SilentProgress
).
I will also ask the QGIS core team if there is a special reason for the removal of these lines. With a bit of luck, they will add them again...
This last bit of the original error:
File "D:\osgeo4w_qgis16\apps\qgis\python\plugins\processing\gui\AlgorithmExecutor.py", line 52, in runalg
progress.error(e.msg)
AttributeError: 'NoneType' object has no attribute 'error'
is saying that progress
is None
, so the progress.error
call fails. This then triggers the first part of the displayed error because QGIS error handler tries to write a message to an iface object that also doesn't exist.
The relevant bit of Processing's python code that generates the original error is:
def runalg(alg, progress=None):
"""Executes a given algorithm, showing its progress in the
progress object passed along.
Return true if everything went OK, false if the algorithm
could not be completed.
"""
try:
alg.execute(progress)
return True
except GeoAlgorithmExecutionException as e:
ProcessingLog.addToLog(sys.exc_info()[0], ProcessingLog.LOG_ERROR)
progress.error(e.msg) ## this line ##
return False
So for some reason the algorithm has raised a GeoAlgorithmExecutionException and progress
is None. I don't know where progress
is meant to come from - perhaps your python script should create something to pass to it. I don't know its raising the GeoAlg error either, or which of the two problems is the one you really need to fix...