Error de importación para qgis.core al ejecutar el script de shell OSGeo4w

17

He estado intentando, junto con esta publicación , ejecutar un script en OSGeo4w Shell , fuera de QGIS. Pero me sale el siguiente error:

ImportError: ningún módulo llamado qgis.core

También leí las siguientes publicaciones e intenté importar varios módulos, pero fue en vano:

Aquí hay un script simple que crea una cuadrícula y recorta un archivo de forma poligonal sobre él.

Nota: Este script se ha probado y funciona correctamente cuando se ejecuta en 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

Siguiendo la respuesta y el guión publicado por @gcarrillo, finalmente puedo importar los qgis.core.módulos con éxito. El script proporcionado por @gcarrillo se ejecuta pero recibo un error de 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'
José
fuente
1
¿Configuró PYTHONPATH correctamente? Sugiero ejecutar el script con las mismas variables ENV establecidas en qgis.bat señaladas por el ícono qgis.
Luigi Pirelli
Gracias @LuigiPirelli, lo intentaré e informaré.
Joseph
Gracias por su sugerencia @LuigiPirelli, pero el problema persiste (¡a menos que agregue las variables ambientales incorrectamente!)
Joseph
1
Para mí, una RUTA de Windows debe establecerse con "set" de esta manera: set path =% OSGEO4W_ROOT% \ apps \ qgis \ bin;% OSGEO4W_ROOT% \ apps \ grass \ grass-grass-6.4.3 \ lib;% PATH%
Stefan

Respuestas:

17

Finalmente encontré la forma correcta de ejecutar algoritmos de procesamiento en scripts independientes de PyQGIS.

Esta respuesta se basa en las respuestas al Problema con la importación qgis.core al escribir un script PyQGIS independiente y al Error: Algoritmo no encontrado , que a su vez se basa en una discusión de la lista de correo Qgis-dev .

Le sugiero que siga el flujo de trabajo dado en Problema con import qgis.core al escribir un script PyQGIS independiente para habilitar sus bibliotecas QGIS en su Shell OSGeo4W. Una vez que tenga sus bibliotecas QGIS funcionando correctamente, podemos pasar a la segunda parte de su pregunta: ejecutar algoritmos de procesamiento en un script PyQGIS independiente.

Modifiqué un poco tu script original y lo probé en Windows 7 y GNU / Linux. Uso la versión de procesamiento 2.2.0-2 y le sugiero que use esta versión, que es la actual en el momento de escribir la respuesta.

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

Tenga en cuenta que he eliminado la creación de la cuadrícula del bucle for, ya que realmente no necesita una nueva cuadrícula para realizar cada clip.

¡Esto debería funcionar!

Germán Carrillo
fuente
¡Hermosa! Aceptaré esta respuesta ya que es mucho más legible y compacta, al menos en mi opinión. Muchas gracias de nuevo amigo!
Joseph
Acabo de notar que este script crea una Processingcarpeta en el escritorio, similar a la contenida en la /qgis.2carpeta. ¿Debería pasar esto?
Joseph
También crea la misma carpeta desde la que lee los archivos de forma y agrega un archivo de base de datos 'qgis' vacío. Lo cual es bastante molesto ya que el script que estoy modificando toma archivos de forma de varias carpetas, lo que significa que estos nuevos archivos / carpetas también están apareciendo. Todavía prefiero esta respuesta a la otra.
Joseph
Derecha @Joseph, no sé acerca de la creación de esas carpetas, el marco de procesamiento las crea por cualquier motivo que no entiendo. Estoy de acuerdo con usted, esta es la respuesta correcta, le evita pasos adicionales y en realidad aprovecha el marco. Gracias por la generosidad!
Germán Carrillo
2
Esto es muy útil. La gran debilidad de QGIS es permitir que los principiantes escriban scripts simples. Es como tirar de los dientes.
Damien
7

Esta respuesta se basa en las respuestas al Problema con la importación qgis.core al escribir un script PyQGIS independiente y a ¿Cómo puedo acceder al 'procesamiento' con Python? .

Le sugiero que siga el flujo de trabajo dado en Problema con import qgis.core al escribir un script PyQGIS independiente para habilitar sus bibliotecas QGIS en su Shell OSGeo4W. Una vez que tenga sus bibliotecas QGIS funcionando correctamente, podemos pasar a la segunda parte de su pregunta: ejecutar algoritmos de procesamiento en un script PyQGIS independiente.

Como en ¿Cómo puedo acceder al 'procesamiento' con Python? , Le daré una solución alternativa hasta que pueda ejecutar algoritmos por nombre (por ejemplo, processing.runalg('provider:algorithm_name')). Uso la versión de procesamiento 2.2.0-2 y le sugiero que use esta versión.

Podemos usar la consola QGIS Python para averiguar dónde se encuentra un script de algoritmo en las carpetas de complementos de procesamiento. Por ejemplo, para saber desde dónde importar qgis:creategrid, escriba en la consola QGIS Python:

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

Debes obtener:

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

lo cual es suficiente para que notemos tanto la ruta del módulo ( processing.algs.qgis.mmqgisx.MMQGISXAlgorithms) como la clase de algoritmo ( mmqgisx_grid_algorithm). Utilizará esta información en el script a continuación.

Modifiqué un poco tu script y lo probé en Windows 7. Es posible que debas ajustar las rutas para ejecutar el script en tu propio entorno.

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

¡Esto debería funcionar!

Como puede ver, he creado una carpeta Test / Grids para que almacene un único Shapefile de cuadrícula en lugar de crear un archivo temporal en cada ciclo for, lo que no parece ser necesario.

Germán Carrillo
fuente
Muchas gracias @ gcarrillo, probaré esto e informaré.
Joseph
¡De nuevo, gracias por tu ayuda! ¡Puedo importar módulos con éxito! Pero cuando ejecuto su script, recibo un error de rastreo. He editado la pregunta para incluir esto.
Joseph
Olvidó crear la carpeta Test/Grids/antes de ejecutar el script.
Germán Carrillo
Lo siento, olvidé mencionar eso. /Grids/Creé la carpeta y se creó el archivo grid.shp. Eso funciona perfectamente! Algo más es el problema.
Joseph
¿Hiciste algún cambio / ajuste en el script? Lo acabo de probar en GNU / Linux sin ningún problema. El error que obtienes es porque el algoritmo Clip no puede acceder a la ruta path_dir + "Grids\grid.shp", lo que seríaC:\Users\your_username\Desktop\Test\Grids\grid.shp
Germán Carrillo
4

Tuve que hacer cambios menores en el script proporcionado por @gcarrillo para incluir la ruta OSGEO4W64 (tuve que reinstalar QGIS a través del instalador OSGEO4W64 ya que usé el instalador independiente inicialmente) e incluir barras dobles. Aquí está el guión final y muchas gracias a todos por su ayuda:

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
José
fuente