¿Por qué es importante el orden de las importaciones en un script de procesamiento PyQGIS independiente?

13

Me encontré con un problema extraño al ejecutar scripts de procesamiento PyQGIS independientes. El orden de las importaciones en el script afecta su ejecución normal.

Puede reproducir el problema abriendo una consola de Python e ingresando el siguiente script (uso GNU / Linux, QGIS 2.6.1, plugin de procesamiento v.2.2.0-2 y Python 2.7.3):

# Prepare the environment
import sys
from qgis.core import QgsApplication
from PyQt4.QtGui import QApplication
app = QApplication([])
QgsApplication.setPrefixPath("/usr", True)
QgsApplication.initQgis()

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

print Processing.getAlgorithm("qgis:creategrid")

# Exit applications
QgsApplication.exitQgis()
QApplication.exit()

Debes obtener:

ALGORITHM: Create grid
    HSPACING <ParameterNumber>
    VSPACING <ParameterNumber>
    WIDTH <ParameterNumber>
    HEIGHT <ParameterNumber>
    CENTERX <ParameterNumber>
    CENTERY <ParameterNumber>
    GRIDTYPE <ParameterSelection>
    CRS <ParameterCrs>
    SAVENAME <OutputVector>

Por otro lado, si cambia el orden de las importaciones (líneas 3 y 4), de esta manera:

from PyQt4.QtGui import QApplication
from qgis.core import QgsApplication

el script ahora regresa ... None, porque no se encontró el algoritmo.

Este problema implica que no puede ejecutar algoritmos de procesamiento fuera de QGIS si (por casualidad) escribe importaciones en el orden incorrecto.

He comprobado en StackOverflow, pero según importa el orden de importación de Python , el orden realmente no debería importar. Además, la Guía de estilo para Python Code nos dice que primero importemos bibliotecas estándar (más genéricas), luego bibliotecas de terceros relacionadas y, finalmente, importaciones específicas de aplicaciones locales. Creo que PyQt4 se encuentra en la segunda categoría de importaciones, mientras que PyQGIS sería una aplicación local específica, por lo que las importaciones de PyQt4 deberían ser lo primero (aunque no soy un experto en esto).

¿Tienes una idea de por qué esto podría suceder? ¿Alguna vez has experimentado algo similar?


EDITAR 1: Cambió las importaciones implícitas ( from abc import *) por las explícitas (por ejemplo, from abc import xyz) como lo sugiere @ mike-t.

Germán Carrillo
fuente
2
Solo quería decir, excelente pregunta con un breve ejemplo reproducible y evidencia de investigación y análisis de esa investigación.
usuario2856

Respuestas:

14

tl; dr

import qgis
import PyQt4
etc

es la forma correcta

Versión larga

Sí, el pedido de importación puede importar y, en el caso de QGIS 2.0 y superiores, sí importa.

Siempre debe importar qgis.coreo qgis.gui, aunque import qgissea ​​suficiente, antes de importar cualquier cosa de PyQt.

Eso parece tonto. ¿Por qué?

En QGIS 2.0 pasamos a usar enlaces de la versión 2 de SIP que hicieron que las API llamaran más a Python como, por ejemplo, convertirá automáticamente los tipos por usted:

1.0 SIP que tenías que hacer:

value.toString()

en 2.0

value

solo funcionará si es un tipo de cadena en el código C ++.

OK y eso qué

El truco es que tenemos que configurar la versión de API en 2 en el código antes de que se configure mi otra cosa, no se puede configurar nuevamente una vez que se ha configurado. Si importa PyQt primero, establecerá el valor en v1, pero todo en QGIS ahora usa v2. Para arreglar esto, lo configuramos en v2 qgis.__init__.pypero tenemos que importar qgisprimero o de lo contrario PyQt gana.

Debido a que todos los complementos en QGIS 2.0 y superiores ahora usan SIP v2, cualquier llamada similar a SIP v1 generará un error al ejecutarse.

Nathan W
fuente
1
Gracias Nathan, no estaba al tanto de tales implicaciones. Me pregunto si este problema está bien documentado para los desarrolladores de PyQGIS. Por ejemplo, esto muestra cómo debería ser un complemento y no menciona nada sobre las importaciones. Sin embargo, supongo que este problema no afecta a los complementos de la misma manera que afecta a las aplicaciones / scripts independientes. (Votaré su respuesta en unos minutos, ya he gastado todos los votos diarios :)).
Germán Carrillo
Sí, no afecta a los complementos porque importamos qgis en c ++ antes de PyQt.
Nathan W
Extraño ... Me sale un "ImportError: Ningún módulo llamado PyQt" cuando lo uso, import PyQtaunque import qgisfunciona. No es que me moleste hasta el punto de que necesito hacer una nueva pregunta, solo me preguntaba si sabes por qué es así. Yo uso Windows 7 con las mismas versiones de procesamiento / python que @gcarrillo.
Joseph
Ese es un error tipográfico de mi parte. Ver editar.
Nathan W