Warum ist die Reihenfolge der Importe in einem eigenständigen PyQGIS-Verarbeitungsskript wichtig?

13

Beim Ausführen von eigenständigen PyQGIS-Verarbeitungsskripten ist ein seltsames Problem aufgetreten. Die Reihenfolge der Importe im Skript wirkt sich auf die normale Ausführung aus.

Sie können das Problem reproduzieren, indem Sie eine Python-Konsole öffnen und das folgende Skript eingeben (ich verwende GNU / Linux, QGIS 2.6.1, Verarbeitungs-Plugin v.2.2.0-2 und 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()

Sie sollten erhalten:

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

Wenn Sie dagegen die Reihenfolge der Importe ändern (Zeilen 3 und 4), gehen Sie folgendermaßen vor:

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

Das Skript gibt nun ... zurück None, da der Algorithmus nicht gefunden wurde.

Dieses Problem impliziert, dass Sie keine Verarbeitungsalgorithmen aus QGIS ausführen können, wenn Sie Importe (zufällig) in der falschen Reihenfolge schreiben.

Ich habe in StackOverflow eingecheckt, aber laut spielt die Reihenfolge beim Importieren von Python keine Rolle. Der Style Guide für Python-Code fordert uns außerdem auf, zuerst Standardbibliotheken (allgemeinere Bibliotheken), dann Bibliotheken von verwandten Drittanbietern und schließlich lokale anwendungsspezifische Importe zu importieren. Ich denke, PyQt4 liegt in der 2. Kategorie der Importe, wohingegen PyQGIS lokal anwendungsspezifisch wäre, so dass PyQt4-Importe an erster Stelle stehen sollten (ich bin jedoch kein Experte in diesem Bereich).

Haben Sie eine Idee, warum dies passieren könnte? Haben Sie jemals etwas Ähnliches erlebt?


EDIT 1: Implizite Importe ( from abc import *) wurden durch explizite (z. B. from abc import xyz) geändert , wie von @ mike-t vorgeschlagen.

Germán Carrillo
quelle
2
Ich wollte nur sagen, ausgezeichnete Frage mit einem kurzen reproduzierbaren Beispiel und Nachweisen der Forschung und Analyse dieser Forschung.
user2856

Antworten:

14

tl; dr

import qgis
import PyQt4
etc

ist der richtige Weg

Lange Version

Ja, die Importreihenfolge kann von Bedeutung sein, und im Fall von QGIS 2.0 und höher ist dies wichtig.

Sie sollten immer importieren qgis.coreoder qgis.guiauch nur import qgis, bevor Sie PyQt-Inhalte importieren.

Das kommt mir albern vor. Warum?

In QGIS 2.0 haben wir auf die Verwendung von SIP-Bindungen der Version 2 umgestellt, wodurch API-Aufrufe mehr Python erhalten, wie z. B. die automatische Konvertierung von Typen für Sie:

1.0 SIP musste man machen:

value.toString()

in 2.0

value

funktioniert nur, wenn es sich um einen Stringtyp im C ++ - Code handelt.

In Ordnung und jetzt

Der Kicker ist, dass wir die API-Version im Code auf 2 setzen müssen, bevor sie auf etwas anderes gesetzt wird. Sie können sie nicht noch einmal setzen, wenn sie einmal gesetzt wurde. Wenn Sie PyQt zuerst importieren, wird der Wert auf v1 gesetzt, aber alles in QGIS verwendet jetzt v2. Um dies zu beheben, setzen wir es auf v2 in qgis.__init__.py, müssen aber qgiszuerst importieren, sonst gewinnt PyQt.

Da alle Plugins in QGIS 2.0 und höher jetzt SIP v2 verwenden, wird bei Ausführung von Aufrufen wie SIP v1 ein Fehler generiert.

Nathan W
quelle
1
Vielen Dank Nathan, ich war mir solcher Implikationen nicht bewusst. Ich frage mich, ob dieses Problem für PyQGIS-Entwickler gut dokumentiert ist. Dies zeigt zum Beispiel, wie ein Plugin aussehen sollte, und erwähnt nichts über Importe. Ich schätze, dieses Problem betrifft Plugins nicht so wie eigenständige Anwendungen / Skripte. (Ich stimme deiner Antwort in ein paar Minuten zu, ich habe bereits alle täglichen Abstimmungen abgegeben :)).
Germán Carrillo
Ja, es wirkt sich nicht auf Plugins aus, da wir qgis in c ++ vor PyQt importieren.
Nathan W
Seltsam ... Ich bekomme einen "ImportError: No module named PyQt" wenn ich benutze import PyQtobwohl es import qgisfunktioniert. Nicht, dass es mich bis zu dem Punkt stört, an dem ich eine neue Frage stellen muss, ich habe mich nur gefragt, ob Sie wissen, warum das so ist. Ich verwende Windows 7 mit den gleichen Verarbeitungs- / Python-Versionen wie @gcarrillo.
Joseph
Das ist ein Tippfehler von mir. Siehe Bearbeiten.
Nathan W