Dlaczego kolejność importu ma znaczenie w samodzielnym skrypcie przetwarzania PyQGIS?

13

Natknąłem się na dziwny problem podczas uruchamiania samodzielnych skryptów przetwarzających PyQGIS. Kolejność importu w skrypcie wpływa na jego normalne wykonanie.

Możesz odtworzyć problem, otwierając konsolę Python i wprowadzając następujący skrypt (używam GNU / Linux, QGIS 2.6.1, wtyczki przetwarzania v.2.2.0-2 i 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()

Powinieneś uzyskać:

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

Z drugiej strony, jeśli zmienisz kolejność importu (linie 3 i 4), w ten sposób:

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

skrypt powraca teraz ... None, ponieważ algorytm nie został znaleziony.

Ten problem oznacza, że ​​nie można uruchomić algorytmów przetwarzania poza QGIS, jeśli (przypadkowo) zapisujesz import w niewłaściwej kolejności.

Sprawdziłem w StackOverflow, ale zgodnie z tym, czy kolejność importowania w Pythonie ma znaczenie , kolejność nie powinna mieć znaczenia. Ponadto Przewodnik po stylu dla kodu Python mówi nam, aby najpierw zaimportować biblioteki standardowe (bardziej ogólne), następnie powiązane biblioteki stron trzecich, a na koniec zaimportować aplikacje lokalne. Myślę, że PyQt4 należy do drugiej kategorii importu, podczas gdy PyQGIS byłby specyficzny dla aplikacji lokalnych, więc import PyQt4 powinien być na pierwszym miejscu (choć nie jestem ekspertem w tej dziedzinie).

Czy masz pojęcie, dlaczego tak się stało? Czy kiedykolwiek doświadczyłeś czegoś podobnego?


EDYCJA 1: Zmieniono import niejawny ( from abc import *) na jawny (np. from abc import xyz), Jak sugeruje @ mike-t.

Germán Carrillo
źródło
2
Chciałem tylko powiedzieć, doskonałe pytanie z krótkim, powtarzalnym przykładem oraz dowodami badań i analizy tych badań.
user2856

Odpowiedzi:

14

tl; dr

import qgis
import PyQt4
etc

jest właściwy sposób

Długa wersja

Tak, kolejność importu może mieć znaczenie, a w przypadku QGIS 2.0 i nowszych ma to znaczenie.

Zawsze powinieneś zaimportować qgis.corelub qgis.guinawet import qgiswystarczy, zanim zaimportujesz jakiekolwiek elementy PyQt.

To wydaje się głupie. Dlaczego?

W QGIS 2.0 przeszliśmy na używanie SIP w wersji 2, która sprawiła, że ​​wywołania API były bardziej Pythonowe, np. Automatycznie konwertuje typy dla Ciebie:

1.0 SIP musiałeś zrobić:

value.toString()

w 2.0

value

będzie działać, jeśli jest to ciąg znaków w kodzie C ++.

Ok, i co

Kickerem jest to, że musimy ustawić wersję API na 2 w kodzie, zanim zostanie ustawione moje coś innego, nie można ustawić go ponownie po ustawieniu. Jeśli najpierw zaimportujesz PyQt, ustawi wartość v1, ale wszystko w QGIS używa teraz v2. Aby to naprawić, ustawiliśmy go na v2, qgis.__init__.pyale qgisnajpierw musimy zaimportować, inaczej PyQt wygra.

Ponieważ wszystkie wtyczki w QGIS 2.0 i nowszych używają teraz SIP v2, wszelkie wywołania podobne do SIP v1 generują błąd podczas działania.

Nathan W.
źródło
1
Dziękuję Nathan, nie wiedziałem o takich implikacjach. Zastanawiam się, czy ten problem jest dobrze udokumentowany dla programistów PyQGIS. Na przykład pokazuje to , jak powinna wyglądać wtyczka i nie wspomina nic o imporcie. Wydaje mi się, że ten problem nie wpływa na wtyczki w taki sam sposób, jak na samodzielne aplikacje / skrypty. (Będę głosować za twoją odpowiedzią za kilka minut, spędziłem już wszystkie codzienne głosy :)).
Germán Carrillo,
Tak, to nie wpływa na wtyczki, ponieważ importujemy qgis w c ++ przed PyQt.
Nathan W
Dziwne ... Dostaję komunikat „ImportError: Brak modułu o nazwie PyQt” podczas używania, import PyQtchociaż import qgisdziała. Nie przeszkadzało mi to do tego stopnia, że ​​muszę zadać nowe pytanie, po prostu zastanawiałem się, czy wiesz, dlaczego tak jest. Używam Windows 7 z tymi samymi wersjami przetwarzania / python jak @gcarrillo.
Joseph
To moja literówka. Zobacz edycję.
Nathan W