¿Importa el procesamiento QGIS en un script de Python independiente?

10

Quiero escribir algunos scripts independientes que usan la caja de herramientas de procesamiento de Qgis.

He leído algunos hilos ( aquí y aquí , por ejemplo), pero todavía no puedo encontrar una solución que funcione.

Usando Qgis 2.16.1 en Ubuntu Xenial 16.04 LTS

La sección de importación de mi script se ve así:

# Python modules
import sys
import time
import os

# Qgis modules
from qgis.core import *
import qgis.utils
from PyQt4.QtCore import QFileInfo, QSettings

¿Alguien sabe lo que me falta para poder importar el módulo de procesamiento?

Con un simple procesamiento de importación , obtengo esto:

Original exception was:
Traceback (most recent call last):
 File "/home/steph/Documents/Projets/20141227-CIM_Bishkek/Scripts/python/00-projets/20160811-AnalysesUAVs/20160811-UAVAnalyse.py", line 36, in <module>
import processing
 File "/usr/lib/python2.7/dist-packages/qgis/utils.py", line 607, in _import
mod = _builtin_import(name, globals, locals, fromlist, level)
ImportError: No module named processing

EDITAR (después del comentario de Joseph)

He intentado así:

# Python modules
import sys
import time
import os

# Qgis modules
from qgis.core import *
import qgis.utils
from PyQt4.QtGui import *
app = QApplication([])
QgsApplication.setPrefixPath("/usr", True)
QgsApplication.initQgis()
from PyQt4.QtCore import QFileInfo, QSettings
#from PyQt4.QtGui import *

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

pero el comportamiento es extraño: mi script se ejecuta hasta el final sin errores, pero parece "saltar" sobre las tareas que se supone que debe realizar :-) En otras palabras, se ejecuta hasta el final pero sin hacer nada.

Admito que mi explicación no es muy clara ... Investigaré más a fondo, pero si alguien tiene una solución mágica (no una solución alternativa) para importar este módulo, ¡por favor!

EDIT 2: agregando todo mi script. Lo siento si es un poco largo ...

# -*- coding: cp1252 -*-
########################################################
## Name: Performs various analyses on UAV imagery using Qgis
## Source Name: UAVanalyse.py
## Version: Python 2.7
## Author: Stephane Henriod
## Usage: Performs a set of analyses on UAV imagery
## Date 11.08.2016
## Modified: 
########################################################


# Import required modules

# Python modules
import sys
import time
import os

# Qgis modules
from qgis.core import *
import qgis.utils
from PyQt4.QtCore import QFileInfo, QSettings

# Custom modules
from config_work import *
import display_msg as disp
import clean_time as cl

def make_raster_layer(raster, log_file):
    """Creates a raster layer from the path to a raster, if the path exists and if the raster is valid

    Param_in:
        raster (string) -- The path to the raster to be transformed into a layer
        log_file (string) -- The path to the log file to write in

    Param_out:
        list: 
            [0] = full path to the raster 
            [1] = raster layer

    """

    if os.path.exists(raster):
        fileName = raster
        fileInfo = QFileInfo(fileName)
        baseName = fileInfo.baseName()
        rlayer = QgsRasterLayer(fileName, baseName)
        if rlayer.isValid():
            return [raster, rlayer]
    else:
        return False

def study_raster(rlayer, log_file):
    """Returns properties of a raster, if this one exists and is valid

    Param_in:
        rlayer (bin) -- A raster layer
        log_file (string) -- The path to the log file to write in

    """

    infos = {}

    if rlayer:
        infos['a - Width'] = rlayer.width()
        infos['b - Height'] = rlayer.height()
        infos['c - Extent'] = rlayer.extent().toString()
        infos['d - # bands'] = rlayer.bandCount()
        infos['e - X resolution'] = rlayer.rasterUnitsPerPixelX()
        infos['f - Y resolution'] = rlayer.rasterUnitsPerPixelY()
        return infos
    else:
        return False


def project_raster(raster, to_crs, log_file):
    """Projects a raster into another crs

    Param_in:
        raster (string) -- The path to the raster to be transformed into a layer
        to_crs (string) -- The coordinate reference system to which the layer must be projected
        log_file (string) -- The path to the log file to write in

    """

    img_out_name = os.path.splitext(os.path.basename(raster))[0] + '_proj' + os.path.splitext(os.path.basename(raster))[1]
    img_out = os.path.join(output_folder, img_out_name)
    #processing.runalg("gdalwarp -overwrite -s_srs EPSG:32642 -t_srs " + to_crs + " " + rlayer[0] + " " + img_out)

    msg = img_out    
    disp.display_msg(log_file, msg, 'a')

    return img_out_name

if __name__ == "__main__":
    t_start_script = time.localtime()
    t_start_script_clean = time.strftime("%Y%m%d-%H%M", t_start_script)

    # Checking the folders
    if not os.path.exists(input_folder_path):
        os.makedirs(input_folder_path)
    if not os.path.exists(temp_folder_path):
        os.makedirs(temp_folder_path)
    if not os.path.exists(output_folder_path):
        os.makedirs(output_folder_path)

    # Creating the output and temp folders
    output_folder = os.path.join(output_folder_path, t_start_script_clean + '-UAVanalyse')
    temp_folder = os.path.join(temp_folder_path, t_start_script_clean + '-UAVanalyse')

    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    if not os.path.exists(temp_folder):
        os.makedirs(temp_folder)

    # Creating the log file
    log_file_name = t_start_script_clean + '-UAVanalyse.log'
    log_file = os.path.join(output_folder, log_file_name)

    # Heading of the log file
    msg = "Performs a set of analyses on UAV imagery" + os.linesep
    msg += "Input folder: " + input_folder_path
    msg += "\n RGB image: " + img_rgb_name
    msg += "\n NIR image: " + img_nir_name
    msg += "\n RGBIR image: " + img_rgbir_name
    msg += "\n DSM file: " + img_dsm_name
    disp.display_msg(log_file, msg, 'w')

    #msg = "Script started on " + cl.clean_time(t_start_script)
    #disp.display_msg(log_file, msg, 'a')


    # Initialize Qgis (source: http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/intro.html)
    msg = 'Initialize Qgis'
    disp.display_msg(log_file, msg, 'a')
    # supply path to qgis install location
    QgsApplication.setPrefixPath("/usr", True)

    # create a reference to the QgsApplication, setting the
    # second argument to False disables the GUI
    qgs = QgsApplication([], False)

    # load providers
    qgs.initQgis()


    # Write your code here to load some layers, use processing algorithms, etc.

    # Make raster layers
    rlayer_rgb = make_raster_layer(img_rgb, log_file)
    rlayer_nir = make_raster_layer(img_nir, log_file)
    rlayer_rgbir = make_raster_layer(img_rgbir, log_file)
    rlayer_dsm = make_raster_layer(img_dsm, log_file)

    all_valid_layers = []
    if rlayer_rgb: all_valid_layers.append(rlayer_rgb)
    if rlayer_nir: all_valid_layers.append(rlayer_nir)
    if rlayer_rgbir: all_valid_layers.append(rlayer_rgbir)
    if rlayer_dsm: all_valid_layers.append(rlayer_dsm)




    # (I) Infos about the layers
    msg = os.linesep + frm_separator + os.linesep + '(I) Infos about the layers' + os.linesep + frm_separator + os.linesep
    disp.display_msg(log_file, msg, 'a')

    i = 1
    for layer in all_valid_layers:
        infos = study_raster(layer[1], log_file)
        msg = '\n (' + str(i) + ') ' + layer[0] + os.linesep
        for item in sorted(infos):
            msg += '\n ' + str(item) + ': ' + str(infos[item]) + os.linesep

        i+=1
        disp.display_msg(log_file, msg, 'a')

    msg = 'List of valid layers:' + os.linesep
    for layer in all_valid_layers:
        msg += layer[0]+ os.linesep
    disp.display_msg(log_file, msg, 'a')


    # (II) Projects the layers into the national coordinate system or any desired system
    msg = os.linesep + frm_separator + os.linesep + '(II) Projecting of the layers' + os.linesep + frm_separator + os.linesep
    disp.display_msg(log_file, msg, 'a')

    i = 1
    for layer in all_valid_layers:
        project_raster(layer[0], to_crs, log_file)




    # When script is complete, call exitQgis() to remove the provider and
    # layer registries from memory
    qgs.exitQgis()
    msg = 'Qgis has been closed'
    disp.display_msg(log_file, msg, 'a')

    #raw_input("Press Enter to continue...")
Stéphane Henriod
fuente
En su segundo enlace, ¿utilizó el código provisto por @ GermánCarrillo? Su código es lo que también uso para ejecutar scripts independientes (edito mis rutas ligeramente cuando uso Windows).
Joseph
¿Cuál es la tarea que estás intentando realizar? :). ¿Podría incluir el código en su pregunta, por favor? Esto podría ayudar a otros a identificar lo que está mal.
Joseph
Estoy tratando de escribir algunas funciones para procesar imágenes UAV. Lo primero que debo hacer es reproyectar, por eso necesito el módulo de procesamiento. Permítanme agregar mi script completo, aunque me da un poco de vergüenza: no soy un desarrollador "real" y estoy seguro de que mi código no es el más claro ni el más sencillo que hayan visto :-)
Stéphane Henriod
¡No te avergüences! Nada de lo que publico es lo más limpio o directo =)
Joseph
Entonces agregué todo mi guión. Siéntase libre de echar un vistazo :-)
Stéphane Henriod

Respuestas:

6

Linux QGIS 2.18.1

Con este código, lo tengo, ejecute Processing desde un script independiente:

#!/usr/bin/env python
import qgis
from qgis.core import *
import sys

app = QgsApplication([],True, None)
app.setPrefixPath("/usr", True)
app.initQgis()
sys.path.append('/usr/share/qgis/python/plugins')
from processing.core.Processing import Processing
Processing.initialize()
from processing.tools import *

print Processing.getAlgorithm("qgis:creategrid")
Juanma Font
fuente
Esta es la única combinación que funcionó para el entorno en el que estoy trabajando (Pycharm C.Ed en una máquina Ubuntu 14.04 con Python 2.7). Antes, probé las combinaciones de gis.stackexchange.com/questions/129513/… y gis.stackexchange.com/questions/176821/… y, lamentablemente, ninguna de ellas importó "processing.core.Processing". No sé por qué importar un módulo es tan confuso. Para el registro: hay un paquete Python puro también llamado "procesamiento" que sombrea el QGIS.
Irene
3

Así que logré que funcionara, gracias @Joseph por tus sugerencias:

# Import required modules

# Python modules
import sys
import time
import datetime
import os
from getpass import getuser

# Qgis modules and environment
from qgis.core import *
import qgis.utils
from PyQt4.QtCore import QFileInfo, QSettings

from PyQt4.QtGui import QApplication
app = QApplication([])

QgsApplication.setPrefixPath("/usr", True)
QgsApplication.initQgis()

# Prepare processing framework
sys.path.append('/home/' + getuser() + '/.qgis2/python/plugins')
from processing.core.Processing import Processing

Processing.initialize()

Y podría probarlo con

print Processing.getAlgorithm("qgis:creategrid")

Supongo que mi problema proviene del hecho de que importé los módulos al comienzo de mi script y luego intenté crear los objetos Qgi desde una función. Supongo que también sería posible hacerlo, pero probablemente haya un defecto en mis habilidades de Python.

Ahora intentaré usar el módulo de procesamiento :-)

Stéphane Henriod
fuente
Algo ha cambiado ? Intento este código (de Joseph) para usar el procesamiento en un script independiente y obtengo: ImportError: No hay un módulo llamado processing.core.Processing Using linux QGIS 2.18.1
Juanma Font