Erro de importação para qgis.core ao executar o script de shell OSGeo4w

17

Venho tentando, junto com este post , executar um script no OSGeo4w Shell , fora do QGIS. Mas eu recebo o seguinte erro:

ImportError: nenhum módulo chamado qgis.core

Também li os seguintes posts e tentei importar vários módulos, mas sem sucesso:

Aqui está um script simples que cria uma grade e prende um shapefile de polígono nela.

Nota: Este script foi testado e funciona com êxito ao executar no QGIS.

##Test=name

import os
import glob
import sys

sys.path.append("C:\Program Files\QGIS Brighton\lib;%OSGEO4W_ROOT:\=/%/apps/qgis;%OSGEO4W_ROOT%\apps\qgis\bin;%OSGEO4W_ROOT%\apps\grass\grass-6.4.3\lib;%PATH%")

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *

QgsApplication.setPrefixPath("C:\Program Files\QGIS Brighton\apps\qgis", True)
QgsApplication.initQgis()

from os.path import expanduser
home = expanduser("~")

#   Folder path of the Results for shapefiles
path_dir = home + "\Desktop\Test\\"
path_res = path_dir + "Results\\"

def run():
#   Set directory, search for all polygon .shp files and run the Create Grid and Clip algorithms then output results into Results folder
    os.chdir(path_dir + "Shapefiles\\")
    for fname in glob.glob("*.shp"):
            outputs_1=processing.runalg("qgis:creategrid", 1000, 1000, 24108, 18351.157175, 258293.802316, 665638.226408, 1, 'EPSG:7405',  None)
            outputs_2=processing.runalg("qgis:clip", outputs_1['SAVENAME'], fname, path_res  + "/"+ fname)
run()

QgsApplication.exitQgis()
#   Remove the above line when running in QGIS

Seguindo a resposta e o script postado por @gcarrillo, finalmente posso importar os qgis.core.módulos com sucesso. O script fornecido por @gcarrillo é executado, mas eu recebo um erro do Traceback:

Traceback (most recent call last):
  File "Test.py", line 55, in <module>
    run()
  File "Test.py", line 53, in run
    algClip.processAlgorithm(progress)
  File "C:\Users\username\.qgis2\python\plugins\processing\algs\qgis\ftools\Clip.py", line 59, in processAlgorithm
    layerA.pendingFields(),
AttributeError: 'NoneType' object has no attribute 'pendingFields'
Joseph
fonte
1
Você configurou o PYTHONPATH corretamente? Sugiro executar o script com as mesmas variáveis ​​ENV definidas no qgis.bat apontado pelo ícone qgis.
Luigi Pirelli
Obrigado @LuigiPirelli, vou dar uma chance e relatar de volta.
Joseph
Obrigado por sua sugestão @LuigiPirelli mas os persiste problema ainda (a menos que eu adicionei as variáveis ambientais de forma incorreta!)
Joseph
1
Para mim, o PATH do Windows deve ser definido com "set" como este: set path =% OSGEO4W_ROOT% \ apps \ qgis \ bin;% OSGEO4W_ROOT% \ apps \ grass \ grass-6.4.3 \ lib;% PATH%
Stefan

Respostas:

17

Finalmente, encontrei a maneira correta de executar algoritmos de processamento em scripts independentes do PyQGIS.

Esta resposta é baseada em respostas ao Problema com a importação qgis.core ao gravar um script PyQGIS independente e ao Erro: Algoritmo não encontrado , que por sua vez é baseado em uma discussão na lista de discussão Qgis-dev .

Sugiro que você siga o fluxo de trabalho fornecido em Problema com a importação qgis.core ao escrever um script PyQGIS independente para ativar suas bibliotecas QGIS no OSGeo4W Shell. Depois de ter suas bibliotecas QGIS funcionando corretamente, podemos prosseguir para a segunda parte da sua pergunta: executando algoritmos de processamento em um script PyQGIS independente.

Modifiquei um pouco o seu script original e testei-o no Windows 7 e GNU / Linux. Eu uso a versão de processamento 2.2.0-2 e sugiro que você use esta versão, que é a atual no momento em que a resposta foi escrita.

import os, sys, glob

# Prepare the environment
from qgis.core import * # qgis.core must be imported before PyQt4.QtGui!!!
from PyQt4.QtGui import *
app = QApplication([])
QgsApplication.setPrefixPath("C:\\Program Files\\QGIS Brighton\\apps\\qgis", True) # The True value is important
QgsApplication.initQgis()

from os.path import expanduser
home = expanduser("~")

#   Folder path of the Results for shapefiles
path_dir = home + "\Desktop\Test\\"
path_res = path_dir + "Results\\"

# Prepare processing framework 
sys.path.append( home + '\.qgis2\python\plugins' )
from processing.core.Processing import Processing
Processing.initialize()
from processing.tools import *

def run():
    outputs_1=general.runalg("qgis:creategrid", 1000, 1000, 24108, 18351.157175, 258293.802316, 665638.226408, 1, 'EPSG:7405',  None)
    #   Set directory, search for all polygon .shp files and run the Create Grid and Clip algorithms then output results into Results folder
    os.chdir(path_dir + "Shapefiles\\")
    for fname in glob.glob("*.shp"):        
        outputs_2=general.runalg("qgis:clip", outputs_1['SAVENAME'], fname, path_res  + "/"+ fname)

run()

QgsApplication.exitQgis()
#   Remove the above line when running in QGIS

Observe que tirei a criação da grade do loop for, pois você realmente não precisa de uma nova grade para executar cada clipe.

Isso deve fazer o truque!

Germán Carrillo
fonte
Lindo! Aceitará esta resposta como muito mais legível e compacta, pelo menos na minha opinião. Muito obrigado novamente amigo!
Joseph
Só notei que esse script cria uma Processingpasta na área de trabalho, semelhante à contida na /qgis.2pasta. Isso deveria acontecer?
Joseph
Ele também cria a mesma pasta da qual lê os shapefiles e adiciona um arquivo de base de dados 'qgis' vazio. O que é bastante irritante, pois o script que estou modificando pega os shapefiles de várias pastas, o que significa que esses novos arquivos / pastas também estão aparecendo. Eu ainda prefiro esta resposta à sua outra.
Joseph
Certo, Joseph, não sei sobre a criação dessas pastas, a estrutura de processamento as cria por qualquer motivo que não entendo. Eu concordo com você, esta é a resposta correta, evita etapas adicionais e, na verdade, tira proveito da estrutura. Obrigado pela recompensa!
Germán Carrillo
2
Isso é muito útil. A grande fraqueza do QGIS é permitir que os iniciantes escrevam scripts simples. É como arrancar dentes.
Damien
7

Esta resposta é baseada em respostas ao Problema com a importação qgis.core ao escrever um script PyQGIS independente e em Como posso acessar o `processing` com o Python? .

Sugiro que você siga o fluxo de trabalho fornecido em Problema com a importação qgis.core ao escrever um script PyQGIS independente para ativar suas bibliotecas QGIS no OSGeo4W Shell. Depois de ter suas bibliotecas QGIS funcionando corretamente, podemos prosseguir para a segunda parte da sua pergunta: executando algoritmos de processamento em um script PyQGIS independente.

Como em Como posso acessar o `processing` com o Python? , Darei uma solução alternativa até que eu possa executar algoritmos por nome (por exemplo, processing.runalg('provider:algorithm_name')). Eu uso a versão 2.2.0-2 de processamento e sugiro que você use esta versão.

Podemos usar o console QGIS Python para descobrir onde um script de algoritmo está localizado nas pastas de plug-in de processamento. Por exemplo, para saber de onde importar qgis:creategrid, escreva no console do QGIS Python:

from processing.core.Processing import Processing
Processing.getAlgorithm('qgis:creategrid')

Você deve obter:

<processing.algs.qgis.mmqgisx.MMQGISXAlgorithms.mmqgisx_grid_algorithm instance at 0xae7382c>

o que é suficiente para percebermos o caminho do módulo ( processing.algs.qgis.mmqgisx.MMQGISXAlgorithms) e a classe do algoritmo ( mmqgisx_grid_algorithm). Você usará essas informações no script abaixo.

Modifiquei um pouco o seu script e testei no Windows 7. Talvez você precise ajustar os caminhos para executar o script em seu próprio ambiente.

import os
import glob
import sys

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *

app = QApplication([])
QgsApplication.setPrefixPath("C:\\Program Files\\QGIS Brighton\\apps\\qgis", True)
QgsApplication.initQgis()

from os.path import expanduser
home = expanduser("~")

#   Folder path of the Results for shapefiles
path_dir = home + "\Desktop\Test\\"
path_res = path_dir + "Results\\"

# Tell Python where you will get processing from
sys.path.append(home + "\.qgis2\python\plugins")

# Reference the algorithms you want to run
from processing.algs.qgis.mmqgisx.MMQGISXAlgorithms import *
from processing.algs.qgis.ftools.Clip import *
algGrid = mmqgisx_grid_algorithm()
algClip = Clip()

from processing.core.SilentProgress import SilentProgress
progress = SilentProgress()

def run():
    # Create a grid 
    grid = path_dir + "Grids\grid.shp"
    algGrid.setParameterValue('HSPACING', 1000)
    algGrid.setParameterValue('VSPACING', 1000)
    algGrid.setParameterValue('WIDTH', 24108)
    algGrid.setParameterValue('HEIGHT', 18351.157175)
    algGrid.setParameterValue('CENTERX', 258293.802316)
    algGrid.setParameterValue('CENTERY', 665638.226408)
    algGrid.setParameterValue('GRIDTYPE', 1)
    algGrid.setParameterValue('CRS', 'EPSG:7405')
    algGrid.setOutputValue('SAVENAME', grid)
    algGrid.processAlgorithm(progress)

    # Set directory, search for all polygon .shp files 
    os.chdir(path_dir + "Shapefiles\\")    
    for fname in glob.glob("*.shp"):
        # Run the Clip algorithm, then output results into Results folder
        algClip.setParameterValue('INPUT', grid)
        algClip.setParameterValue('OVERLAY', fname)
        algClip.setOutputValue('OUTPUT', path_res  + "/"+ fname)
        algClip.processAlgorithm(progress)

run()
QgsApplication.exitQgis()

Isso deve fazer o truque!

Como você pode ver, eu criei uma pasta Test / Grids para que você armazene um Shapefile de grade única em vez de criar um arquivo temporal em cada loop for, o que não parece ser necessário.

Germán Carrillo
fonte
Muito obrigado @ gcarrillo, vou testar isso e relatar de volta.
Joseph
Mais uma vez, muito obrigado pela sua ajuda! Posso importar módulos com sucesso! Mas quando executo seu script, recebo um erro do Traceback. Eu editei a pergunta para incluir isso.
Joseph
Você esqueceu de criar a pasta Test/Grids/antes de executar o script.
Germán Carrillo
Desculpe, esqueci de mencionar isso. Eu criei a /Grids/pasta e o arquivo grid.shp é criado. Isso funciona perfeitamente! Outra coisa é o problema.
Joseph
Você fez alguma alteração / ajuste no script? Acabei de testar no GNU / Linux sem nenhum problema. O erro que você recebe é porque o algoritmo Clip não pode acessar o caminho path_dir + "Grids\grid.shp", o que seria:C:\Users\your_username\Desktop\Test\Grids\grid.shp
Germán Carrillo
4

Eu tive que fazer pequenas alterações no script fornecido pelo @gcarrillo para incluir o caminho OSGEO4W64 (eu tive que reinstalar o QGIS através do instalador OSGEO4W64, pois usei o instalador independente inicialmente) e para incluir barras duplas. Aqui está o script final e muito obrigado a todos por sua ajuda:

import os, sys, glob

# Prepare the environment
from qgis.core import * # qgis.core must be imported before PyQt4.QtGui!!!
from PyQt4.QtGui import *
app = QgsApplication([]) # instantiation of QgsApplication
QgsApplication.setPrefixPath("C:\\OSGeo4W64\\apps\\qgis", True) # The True value is important
QgsApplication.initQgis()

from os.path import expanduser
home = expanduser("~")

#   Folder path of the Results for shapefiles
path_dir = home + "\Desktop\Test\\"
path_res = path_dir + "Results\\"

# Prepare processing framework 
sys.path.append( home + '\.qgis2\python\plugins' )
from processing.core.Processing import Processing
Processing.initialize()
from processing.tools import *

def run():
    outputs_1=general.runalg("qgis:creategrid", 1000, 1000, 24108, 18351.157175, 258293.802316, 665638.226408, 1, 'EPSG:7405',  None)
    #   Set directory, search for all polygon .shp files and run the Create Grid and Clip algorithms then output results into Results folder
    os.chdir(path_dir + "Shapefiles\\")
    for fname in glob.glob("*.shp"):        
        outputs_2=general.runalg("qgis:clip", outputs_1['SAVENAME'], fname, path_res  + "/"+ fname)
run()

QgsApplication.exitQgis()
#   Remove the above line when running in QGIS
Joseph
fonte