Почему порядок импорта имеет значение в автономном скрипте обработки PyQGIS?

13

Я столкнулся со странной проблемой при запуске автономных сценариев обработки PyQGIS. Порядок импорта в сценарии влияет на его нормальное выполнение.

Вы можете воспроизвести проблему, открыв консоль Python и введя следующий скрипт (я использую GNU / Linux, QGIS 2.6.1, плагин обработки v.2.2.0-2 и 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()

Вы должны получить:

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

С другой стороны, если вы измените порядок импорта (строки 3 и 4), то это так:

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

сценарий теперь возвращается ... None, потому что алгоритм не был найден.

Эта проблема подразумевает, что вы не можете запускать алгоритмы обработки из QGIS, если вы (случайно) пишете импорт в неправильном порядке.

Я проверил в StackOverflow, но в зависимости от того, имеет ли значение порядок импорта Python , порядок не должен иметь значения. Более того, в Руководстве по стилю для кода Python говорится, что мы сначала должны импортировать стандартные (более общие) библиотеки, затем связанные сторонние библиотеки и, наконец, импортировать специфичные для локальных приложений приложения. Я думаю, что PyQt4 находится во 2-й категории импорта, тогда как PyQGIS будет зависеть от локального приложения, поэтому импорт PyQt4 должен стоять первым (хотя я не эксперт в этом, хотя).

У вас есть идея, почему это может произойти? Вы когда-нибудь испытывали нечто подобное?


РЕДАКТИРОВАТЬ 1: Изменен неявный import ( from abc import *) на явный (например, from abc import xyz), как предложено @ mike-t.

Герман Каррильо
источник
2
Просто хотел сказать, отличный вопрос с коротким воспроизводимым примером и доказательством исследования и анализа этого исследования.
user2856

Ответы:

14

ТЛ; др

import qgis
import PyQt4
etc

это правильный путь

Длинная версия

Да, порядок импорта может иметь значение, и в случае QGIS 2.0 и выше он имеет значение.

Вы должны всегда импортировать qgis.coreили qgis.guiдаже import qgisдостаточно, прежде чем импортировать какие-либо вещи PyQt.

Это кажется глупым. Почему?

В QGIS 2.0 мы переключились на использование привязки версии 2 SIP, что сделало вызовы API более Python, например, он будет автоматически преобразовывать типы для вас:

1.0 SIP вы должны были сделать:

value.toString()

в 2.0

value

будет просто работать, если это строковый тип в коде C ++.

Хорошо, так что

Главное, что мы должны установить версию API на 2 в коде, прежде чем он установит что-то еще, вы не можете установить его снова, как только он будет установлен. Если вы сначала импортируете PyQt, он установит значение v1, но все в QGIS теперь использует v2. Чтобы это исправить, мы устанавливаем v2, qgis.__init__.pyно qgisсначала нужно импортировать, иначе PyQt выигрывает.

Поскольку все плагины в QGIS 2.0 и выше теперь используют SIP v2, любые вызовы, подобные SIP v1, вызовут ошибку при запуске.

Натан У
источник
1
Спасибо, Натан, я не знал о таких последствиях. Интересно, хорошо ли задокументирована эта проблема для разработчиков PyQGIS. Например, это показывает, как должен выглядеть плагин, и ничего не упоминает об импорте. Я думаю, что эта проблема не влияет на плагины так же, как на автономные приложения / скрипты. (Я опишу ваш ответ через несколько минут, я уже потратил все ежедневные голоса :)).
Герман Каррильо
Да, это не влияет на плагины, потому что мы импортируем qgis в c ++ до PyQt.
Натан У
Странно ... Я получаю "ImportError: Нет модуля с именем PyQt" при использовании import PyQtхотя import qgisработает. Не то чтобы это беспокоило меня до такой степени, что мне нужно было задать новый вопрос, было просто интересно, знаете ли вы, почему это так. Я использую Windows 7 с той же версией обработки / Python, что и @gcarrillo.
Джозеф
Это опечатка мной. Смотрите редактировать.
Натан В.