Por que a ordem das importações é importante em um script de processamento PyQGIS independente?

13

Eu me deparei com um problema estranho ao executar scripts de processamento PyQGIS independentes. A ordem das importações no script afeta sua execução normal.

Você pode reproduzir o problema abrindo um console Python e inserindo o seguinte script (eu uso o GNU / Linux, QGIS 2.6.1, plugin de processamento v.2.2.0-2 e 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()

Você deve obter:

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

Por outro lado, se você alternar a ordem das importações (linhas 3 e 4), desta maneira:

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

o script agora retorna ... None, porque o algoritmo não foi encontrado.

Esse problema implica que você não pode executar algoritmos de processamento fora do QGIS se (por acaso) gravar importações na ordem errada.

Eu verifiquei no StackOverflow, mas de acordo com o pedido de importação do Python importa , o pedido não deve realmente importar. Além disso, o Guia de Estilo para Código Python nos diz para importar bibliotecas padrão (mais genéricas) primeiro, depois bibliotecas de terceiros relacionadas e, finalmente, importações específicas de aplicativos locais. Eu acho que o PyQt4 está na 2ª categoria de importações, enquanto o PyQGIS seria específico do aplicativo local, portanto as importações do PyQt4 devem vir primeiro (embora não seja especialista nisso).

Você tem uma idéia de por que isso poderia acontecer? Você já experimentou algo semelhante?


EDIT 1: Alteradas importações implícitas ( from abc import *) por explícitas (por exemplo, from abc import xyz) como sugerido por @ mike-t.

Germán Carrillo
fonte
2
Só queria dizer, excelente pergunta com um pequeno exemplo reproduzível e evidências de pesquisa e análise dessa pesquisa.
usar o seguinte comando

Respostas:

14

tl; dr

import qgis
import PyQt4
etc

é a maneira correta

Versão longa

Sim, a ordem de importação pode importar e, no caso do QGIS 2.0 e superior, importa.

Você sempre deve importar qgis.coreou qgis.gui, mesmo que import qgisseja o suficiente, antes de importar qualquer material PyQt.

Isso parece bobagem. Por quê?

No QGIS 2.0, passamos a usar as ligações da versão 2 do SIP, o que fez com que a API chamasse mais Python, como por exemplo, ele converterá automaticamente os tipos para você:

1.0 SIP que você tinha que fazer:

value.toString()

em 2.0

value

funcionará apenas se for um tipo de string no código C ++.

Tá, e daí

O problema é que precisamos definir a versão da API como 2 no código antes que ela seja configurada como outra coisa; você não pode defini-la novamente depois de configurada. Se você importar o PyQt primeiro, ele definirá o valor como v1, mas tudo no QGIS agora usa a v2. Para corrigir isso, definimos como v2, qgis.__init__.pymas temos que importar qgisprimeiro, ou então o PyQt vence.

Como todos os plug-ins no QGIS 2.0 e acima agora usam o SIP v2, qualquer chamada semelhante ao SIP v1 gera um erro ao executar.

Nathan W
fonte
1
Obrigado Nathan, eu não estava ciente de tais implicações. Gostaria de saber se esse problema está bem documentado para os desenvolvedores do PyQGIS. Por exemplo, isso mostra como deve ser um plug-in e não menciona nada sobre importações. Acho que esse problema não afeta os plugins da mesma maneira que afeta aplicativos / scripts independentes. (Vou votar sua resposta em alguns minutos, já gastei todos os votos diários :)).
Germán Carrillo
Sim, isso não afeta plugins porque importamos qgis em c ++ antes do PyQt.
Nathan W
Estranho ... Eu recebo um "ImportError: Nenhum módulo chamado PyQt" ao usar, import PyQtembora import qgisfuncione. Não que isso me incomode a ponto de eu precisar fazer uma nova pergunta, estava apenas me perguntando se você sabe por que isso acontece. Eu uso o Windows 7 com as mesmas versões de processamento / python que o @gcarrillo.
Joseph
Isso é um erro de digitação por mim. Veja editar.
Nathan W