QGIS 2.16: process.runalg schlägt fehl, wenn es außerhalb von QGIS in einer benutzerdefinierten Anwendung ausgeführt wird

8

Ich entwickle das RQGIS-Paket. Um QGIS in R auszuführen, rufe ich QGIS über die Befehlszeile auf. Dies funktionierte perfekt mit QGIS 2.14. Das Ausführen des gleichen Codes mit QGIS 2.16 führt jedoch zu einem Fehler. Folgendes mache ich:

Zuerst setze ich alle notwendigen Pfade in der Eingabeaufforderung:

@echo off
SET OSGEO4W_ROOT=D:\osgeo4w_qgis16
call "%OSGEO4W_ROOT%"\bin\o4w_env.bat
@echo off
path %PATH%;%OSGEO4W_ROOT%\apps\qgis\bin
set PYTHONPATH=%PYTHONPATH%;%OSGEO4W_ROOT%\apps\qgis\python;
set QGIS_PREFIX_PATH=%OSGEO4W_ROOT%\apps\qgis
rem open python     
python.exe

Anschließend führe ich in Python folgende Zeilen aus:

import os
import sys
from qgis.core import *
import qgis.utils
from osgeo import ogr
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.gui import *
QgsApplication.setPrefixPath('D:\osgeo4w_qgis16\apps\qgis', True)
app = QgsApplication([], True)
QgsApplication.initQgis()
sys.path.append(r'D:\osgeo4w_qgis16\apps\qgis\python\plugins')
from processing.core.Processing import Processing
Processing.initialize()
import processing
processing.alglist()
processing.alghelp("grass7:v.voronoi")

Das funktioniert. Aufruf von process.runalg ...

from processing.tests.TestData import points
result = processing.runalg('grass7:v.voronoi', points(), False, False, '270778.60198,270855.745301,4458921.97814,4458983.8488', -1, 0.0001, 0, None,)

... erzeugt diese Fehlermeldung:

Error in sys.excepthook:
Traceback (most recent call last):
  File "D:\osgeo4w_qgis16\apps\qgis\python\qgis\utils.py", line 196, in qgis_excepthook
    showException(type, value, tb, None, messagebar=True)
  File "D:\osgeo4w_qgis16\apps\qgis\python\qgis\utils.py", line 107, in showException
    open_stack_dialog(type, value, tb, msg)
  File "D:\osgeo4w_qgis16\apps\qgis\python\qgis\utils.py", line 142, in open_stack_dialog
    iface.messageBar().popWidget()
AttributeError: 'NoneType' object has no attribute 'messageBar'

Original exception was:
Traceback (most recent call last):
  File "<stdin>", line 10, in <module>
  File "D:\osgeo4w_qgis16\apps\qgis\python\plugins\processing\tools\general.py", line 75, in runalg
    alg = Processing.runAlgorithm(algOrName, None, *args, **kwargs)
  File "D:\osgeo4w_qgis16\apps\qgis\python\plugins\processing\core\Processing.py", line 304, in runAlgorithm
    ret = runalg(alg, progress)
  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'
Jannes
quelle

Antworten:

5

Der Verarbeitungsfehler wurde kürzlich behoben, siehe https://github.com/qgis/QGIS/commit/df2ca2e60798315d816966f25aa024b93835f776

Victor Olaya
quelle
1
Victor, obwohl Sie sagten, das Problem sei behoben, bleibt es am Leben. Kürzlich wurde QGIS 2.18 veröffentlicht. Aber dennoch muss man manuell ersetzen alg.execute(progress)durch alg.execute(progress or SilentProgress())in AlgorithmExecutor.py QGIS in einer benutzerdefinierten Anwendung zu verwenden. Das Problem ist noch schlimmer geworden, da jetzt keine Fehlermeldung mehr auftritt. Stattdessen gibt es sogar Erfolgsmeldungen (z. B. beim Ausführen saga:catchmentarearecursive), nur die angegebenen Ausgabeordner bleiben leer. Ich würde mich sehr freuen, wenn Sie dieses Problem beheben könnten. Oder fehlt mir etwas?
Jannes
5

Barry, danke für deinen Rat. Anscheinend hat das QGIS-Kernteam den Code geändert. In QGIS 2.14 runalgwurde wie folgt definiert:

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

Wenn also der Fortschritt gleich ist None(was in meinem Beispielcode der Fall ist), haben Sie SilentProgresssich darum gekümmert. Im Gegensatz dazu wurde in QGIS 2.16 die entsprechende if-Anweisung entfernt (siehe Barrys Antwort oben), was zum Scheitern von führt runalg. Eine Lösung wäre, das Skript AlgorithmExecutor.py manuell zu bearbeiten, indem die fehlenden Zeilen erneut hinzugefügt werden. In diesem Fall müsste am Anfang des Skripts ( from processing.core.SilentProgress import SilentProgress) eine weitere Importzeile hinzugefügt werden .

Ich werde auch das QGIS-Kernteam fragen, ob es einen besonderen Grund für die Entfernung dieser Leitungen gibt. Mit etwas Glück werden sie sie wieder hinzufügen ...

Jannes
quelle
Das Hinzufügen der beiden obigen Zeilen und der import-Anweisung zum Skript AlgorithmExecutor.py hat bei mir funktioniert! Ich habe letzte Woche ein Upgrade auf 2.16 durchgeführt und war auch daran gehängt. Vielen Dank!
RickD
Ich habe gerade ein Upgrade von 2.8.2 auf 2.16.3 durchgeführt und bin bei einigen von mir ausgeführten externen Python-Skripten auf dieselben Probleme gestoßen. Die oben genannten Änderungen haben das Problem für mich behoben. Danke Jannes und Spacedman.
BStone
4

Das letzte Stück des ursprünglichen Fehlers:

  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'

sagt das progressist None, also progress.errorschlägt der Anruf fehl. Dies löst dann den ersten Teil des angezeigten Fehlers aus, da der QGIS-Fehlerbehandler versucht, eine Nachricht in ein iface-Objekt zu schreiben, das ebenfalls nicht vorhanden ist.

Das relevante Bit des Python-Codes von Processing, das den ursprünglichen Fehler generiert, ist:

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

Aus irgendeinem Grund hat der Algorithmus eine GeoAlgorithmExecutionException ausgelöst und progressist None. Ich weiß nicht, woher progresses kommen soll - vielleicht sollte Ihr Python-Skript etwas erstellen, um es weiterzugeben. Ich weiß auch nicht, ob es den GeoAlg-Fehler auslöst oder welches der beiden Probleme das ist, das Sie wirklich beheben müssen ...

Spacedman
quelle