スタンドアロンの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でチェックしましたが、Does Python import order matterに従って、順序は実際には重要ではありません。さらに、Pythonコードのスタイルガイドでは、最初に標準(より一般的な)ライブラリをインポートし、次に関連するサードパーティライブラリをインポートし、最後にローカルアプリケーション固有のインポートを行うように指示しています。PyQt4はインポートの2番目のカテゴリにあると思いますが、PyQGISはローカルアプリケーション固有であるため、PyQt4のインポートを最初に行う必要があります(ただし、私はこれについての専門家ではありません)。

これがなぜ起こるのか、あなたは考えていますか?同様のことを経験したことがありますか?


編集1:@ mike-tが示唆するようにfrom abc import *、明示的なインポート(例えば)によって暗黙的なインポート()を変更しましたfrom abc import xyz


2
ちょうど言いたかった、短い再現可能な例と研究の証拠とその研究の分析を伴う優れた質問。
user2856

回答:


14

tl; dr

import qgis
import PyQt4
etc

正しい方法です

ロングバージョン

はい、インポート順序は重要です。QGIS2.0以降の場合は重要です。

PyQtをインポートする前に、常にimport qgis.coreまたはqgis.guiimport qgis十分です。

それはばかげているようです。どうして?

QGIS 2.0では、SIPのバージョン2バインディングの使用に切り替えました。これにより、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開発者向けに十分に文書化されているのでしょうか。たとえば、これはプラグインがどのように見えるべきかを示しており、インポートについては何も言及していません。ただし、この問題は、スタンドアロンのアプリケーション/スクリプトに影響するのと同じように、プラグインには影響しないと思います。(私は数分後にあなたの答えに賛成します、私はすでにすべての毎日の投票を費やしました:))。
ゲルマンカリージョ

はい、PyQtの前にc ++でqgisをインポートするため、プラグインには影響しません。
ネイサンW

奇妙な...私は動作しますが、使用すると「ImportError:No module named PyQt」というメッセージimport PyQtが表示されimport qgisます。新しい質問をする必要があるという点で私を悩ませているわけではなく、これがなぜかを知っているのかどうか疑問に思っていました。@gcarrilloと同じ処理/ PythonバージョンのWindows 7を使用しています。
ジョセフ

それは私によるタイプミスです。編集を参照してください。
ネイサンW
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.