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...