QGIS 2.16: processing.runalg échoue lorsqu'il est exécuté en dehors de QGIS dans une application personnalisée

8

Je développe le package RQGIS. Pour exécuter QGIS à partir de R, j'appelle QGIS via la ligne de commande. Cela fonctionnait parfaitement avec QGIS 2.14. Cependant, l'exécution du même code avec QGIS 2.16 génère une erreur. Voici ce que je fais:

Tout d'abord, j'ai défini tous les chemins nécessaires dans l'invite de commande:

@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

Par la suite, je lance les lignes suivantes en Python:

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")

Cela marche. Cependant, appeler processing.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,)

... produit ce message d'erreur:

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
la source

Réponses:

5

L'erreur de traitement a été corrigée récemment, voir https://github.com/qgis/QGIS/commit/df2ca2e60798315d816966f25aa024b93835f776

Victor Olaya
la source
1
Victor, bien que vous ayez dit que le problème était résolu, il est toujours d'actualité. Récemment, QGIS 2.18 a été publié. Mais encore faut-il remplacer manuellement alg.execute(progress)par alg.execute(progress or SilentProgress())dans AlgorithmExecutor.py pour utiliser QGIS dans une application personnalisée. Le problème est devenu encore pire depuis qu'il n'y a plus de message d'erreur. Au lieu de cela, il y a même des messages de réussite (par exemple lors de l'exécution saga:catchmentarearecursive), seuls les dossiers de sortie spécifiés restent vides. J'apprécierais grandement si vous pouviez résoudre ce problème. Ou est-ce que je manque quelque chose?
Jannes
5

Barry, merci pour tes conseils. Apparemment, l'équipe principale de QGIS a changé le code. Dans QGIS 2.14 a runalgété défini comme suit:

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

Donc, si la progression est égale à None(ce qui est le cas dans mon exemple de code), SilentProgressprenez-en soin. En revanche, dans QGIS 2.16, l'instruction if correspondante a été supprimée (voir la réponse de Barry ci-dessus), ce qui entraîne l'échec de runalg. Une solution serait de modifier manuellement le script AlgorithmExecutor.py en ajoutant à nouveau les lignes manquantes. Dans ce cas, il faudrait ajouter une autre ligne d'importation au début du script ( from processing.core.SilentProgress import SilentProgress).

Je demanderai également à l'équipe principale de QGIS s'il existe une raison particulière pour la suppression de ces lignes. Avec un peu de chance, ils les ajouteront à nouveau ...

Jannes
la source
l'ajout des 2 lignes ci-dessus et de l'instruction import au script AlgorithmExecutor.py a fonctionné pour moi! Je viens de passer à 2.16 la semaine dernière et j'ai également raccroché à ce sujet. Merci!
rickD
Je viens de passer de la 2.8.2 à la 2.16.3 et j'ai rencontré les mêmes problèmes avec certains scripts python externes que j'exécute. Faire les changements ci-dessus a résolu le problème pour moi. Merci Jannes et Spacedman.
BStone
4

Ce dernier bit de l'erreur d'origine:

  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'

dit que progressc'est None, donc l' progress.errorappel échoue. Cela déclenche ensuite la première partie de l'erreur affichée car le gestionnaire d'erreurs QGIS essaie d'écrire un message sur un objet iface qui n'existe pas non plus.

Le bit pertinent du code python de Processing qui génère l'erreur d'origine est:

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

Donc, pour une raison quelconque, l'algorithme a déclenché une GeoAlgorithmExecutionException et progressest None. Je ne sais pas d'où progressest censé provenir - peut-être que votre script python devrait créer quelque chose pour lui passer. Je ne sais pas non plus si cela soulève l'erreur GeoAlg, ou lequel des deux problèmes est celui que vous devez vraiment résoudre ...

Spacedman
la source