QGIS 2.16: processing.runalg falha quando executado fora do QGIS em um aplicativo personalizado

8

Estou desenvolvendo o pacote RQGIS. Para executar o QGIS a partir do R, chamo o QGIS através da linha de comando. Isso funcionou perfeitamente com o QGIS 2.14. A execução do mesmo código com o QGIS 2.16, no entanto, produz um erro. Aqui está o que eu faço:

Primeiro, defino todos os caminhos necessários no prompt de comando:

@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

Posteriormente, eu executo as seguintes linhas no 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")

Isso funciona. No entanto, chamando 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,)

... produz esta mensagem de erro:

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
fonte

Respostas:

5

O erro de processamento foi corrigido recentemente, consulte https://github.com/qgis/QGIS/commit/df2ca2e60798315d816966f25aa024b93835f776

Victor Olaya
fonte
1
Victor, embora você tenha dito que o problema foi resolvido, ele ainda permanece vivo. Recentemente, o QGIS 2.18 foi lançado. Mas ainda é necessário substituir manualmente alg.execute(progress)por alg.execute(progress or SilentProgress())AlgorithmExecutor.py para usar o QGIS em um aplicativo personalizado. O problema ficou ainda pior, pois agora não há nenhuma mensagem de erro. Em vez disso, existem até mensagens de sucesso (por exemplo, durante a execução saga:catchmentarearecursive), apenas as pastas de saída especificadas permanecem vazias. Eu apreciaria muito se você pudesse resolver esse problema. Ou eu estou esquecendo de alguma coisa?
Janes
5

Barry, obrigado pelo seu conselho. Aparentemente, a equipe principal do QGIS mudou o código. No QGIS 2.14 runalgfoi definido da seguinte forma:

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

Portanto, se o progresso for igual a None(que é o caso no meu código de exemplo), SilentProgresscuidei dele. Por outro lado, no QGIS 2.16, a declaração if correspondente foi removida (consulte a resposta de Barry acima), o que leva à falha de runalg. Uma solução seria editar manualmente o script AlgorithmExecutor.py adicionando novamente as linhas ausentes. Nesse caso, seria necessário adicionar outra linha de importação ao início do script ( from processing.core.SilentProgress import SilentProgress).

Também perguntarei à equipe principal do QGIS se existe um motivo especial para a remoção dessas linhas. Com um pouco de sorte, eles os adicionarão novamente ...

Jannes
fonte
adicionar as 2 linhas acima e a declaração de importação ao script AlgorithmExecutor.py funcionou para mim! Acabei de atualizar para a versão 2.16 na semana passada e também desliguei. Obrigado!
RickD 22/08/16
Acabei de atualizar do 2.8.2 para o 2.16.3 e encontrei os mesmos problemas com alguns scripts python externos que eu corro. Fazer as alterações acima corrigiu o problema para mim. Obrigado Jannes e Spacedman.
BStone 27/09/16
4

Este último bit do erro original:

  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'

está dizendo que progressé None, por isso a progress.errorchamada falha. Isso aciona a primeira parte do erro exibido porque o manipulador de erros QGIS tenta gravar uma mensagem em um objeto iface que também não existe.

O bit relevante do código python do Processing que gera o erro original é:

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

Portanto, por algum motivo, o algoritmo gerou uma GeoAlgorithmExecutionException e progressé None. Eu não sei de onde ele progressdeve vir - talvez o seu script python deva criar algo para passar para ele. Também não sei o que está causando o erro GeoAlg, ou qual dos dois problemas é o que você realmente precisa corrigir ...

Spacedman
fonte