バージョン2.xと3.xの両方でQGIS pythonプラグインを作成しますか?


12

QGIS pythonプラグインをからQGIS 2に移行し、QGIS 3さまざまなリソースを閲覧しています。

プラグインが両方のバージョンと互換性があるかどうか、またはプラグインバージョンに2つのハンドルが必要かどうかは明確ではありません。

私がこれまでに遭遇した問題は、PyQtインポート(PyQt4 / PyQt5)を管理する方法です。

回答:


18

ドキュメンテーション

ここでは、PyQGIS APIの下で何が新しく、何が壊れているかを見つけることができます
python3にどのポートPython2の詳細を取得するには、そこに行きます

この質問については、QGIS2からQGIS3へのテストに関する詳細を見つけることができます:QGISプラグインの自動テストの作成?

また、移行ツールに関するOpenGis.chの興味深い論文がここにあります。

私のコードに何が変わるのか

実際、新しいバージョンを渡す準備ができていないプラグインのコードを変更する必要があります。

QGISバージョンを確認するために作成されたqgis.utils.QGis.QGIS_VERSION_INT関数を取得します。これは、関数がデキャブルされている場合に役立ちます。exempleについてはsetSelectedFeatures2.16以来。

ifステートメントを使用した例:

if qgis.utils.QGis.QGIS_VERSION_INT < 21600 :
            joinLayer.setSelectedFeatures( [ f.id() for f in request ] )
        else:
            joinLayer.selectByIds(  [ f.id() for f in request ] )

PyQtモジュールの下にインポートするオブジェクトについても同じです。互換性が必要な場合、価格はより多くのコード行を記述することです(QGIS2関数を含むコードとQGIS3関数を含むコード、およびバージョンをチェックするためのコードと新しいライブラリをインポートする機能)。

PyQtライブラリについて

PyQt5はPyQt4と下位互換性がありません。PyQt5にはいくつかの重要な変更があります。ただし、古いコードを新しいライブラリに調整することはそれほど難しくありません。違いは、とりわけ次のとおりです。

  • Pythonモジュールが再編成されました。一部のモジュールは削除され(QtScript)、他のモジュールはサブモジュールに分割されました(QtGui、QtWebKit)。

  • QtBluetooth、QtPositioning、またはEnginioなどの新しいモジュールが導入されました。

  • PyQt5は、新しいスタイルの信号とスロットのハンドライトのみをサポートします。SIGNAL()またはSLOT()の呼び出しはサポートされなくなりました。PyQt5は、Qt v5.0で非推奨または廃止としてマークされたQt APIの部分をサポートしません。

ソース:(http://zetcode.com/gui/pyqt5/introduction/

from / importステートメントへの変更の例を次に示します。

PyQt4では、APIのドキュメント
を確認する
必要がありました。たとえば、PyQT4 QtCoreモジュールの
例PyQT4 QtGuiモジュール

from PyQt4.QtCore import QSettings, QTranslator, qVersion, QCoreApplication, Qt, QObject, SIGNAL

from PyQt4.QtGui import QAction, QIcon, QDialog, QFormLayout

そして、PyQt5では、これらのAPIのドキュメントを確認する必要があり
ます。PyQt5QtCore モジュール
PyQt5 QtGuiモジュール

そのようになります:

from PyQt5.QtCore import QSettings, QTranslator, QVersionNumber, QCoreApplication, Qt, QObject, pyqtSignal 
from PyQt5.QtGui import QIcon 
from PyQt5.QtWidgets import QAction, QDialog, QFormLayout

ご了承ください :

QtGuiモジュールはサブモジュールに分割されました。QtGuiモジュールには、ウィンドウシステムの統合、イベント処理、2Dグラフィックス、基本的なイメージング、フォント、テキストのクラスが含まれています。また、OpenGLおよびOpenGL ESバインディングの完全なセットも含まれています(OpenGLのサポートを参照)。アプリケーション開発者は通常、これをQtWidgetsモジュールに含まれるような高レベルのAPIで使用します。

そして、PyQt5は新しいスタイルのシグナルとスロットのハンドライトのみをサポートします!このページを見てい使用方法を理解するためpyqtSignalconnectおよびeイベントオブジェクトの代わりに使用しますSIGNAL

互換性を持たせる

そのため、PyQt4 / PyQt5(およびQGIS2 / QGIS3)間の互換性があるため、pyQt5ライブラリを使用する前にインポートを試す/除外する必要があります。

try:
    from PyQt5.QtCore import QSettings, QTranslator, QVersionNumber, QCoreApplication, Qt, QObject, pyqtSignal 
    from PyQt5.QtGui import QIcon 
    from PyQt5.QtWidgets import QAction, QDialog, QFormLayout

except:
    from PyQt4.QtCore import QSettings, QTranslator, qVersion, QCoreApplication, Qt, QObject, SIGNAL
    from PyQt4.QtGui import QAction, QIcon, QDialog, QFormLayout

また、try / exceptまたはifステートメントを追加して、コード内の特定の関数も変更する必要があることを忘れないでください。


2
グレート答え、う大いに助けが最初のいずれかを交換することである何かfrom PyQt4.QtCore import *from PyQt4.QtCore import QSomething, QWhatever, QElse、これはそう何のtry-除く輸入が必要とされ、移行スクリプトは、(モジュールが変更に必要な調整を含む)が適切に最後のステップを間に合わせるんだろう。
マティアスクーン

あなたは正しい*私はそれをシンプルに保つために使用しましたが、あなたのフィードバックのおかげでそれを変更します
ヒューゴ・ルーサファ-GeoDatup

ここでは、それは実際に違いを生むんので、このトピックでは、*インポートしを使用しないように人々に伝えるのに最適な場所です
マティアス・クーン

@Hugo:非常に詳細な答えであり、開始するのに大いに役立ちました。すでに引用した多数の有用なリソースにqgis2compatプラグインを追加します。
sigeal

それは素晴らしいアイデアです。回答は自由に編集できます。フィードバックをありがとう
ヒューゴルーサファ-GeoDatup

2

そのようなものを試してください:

try:
    # action for QGIS 3/PyQt5
except:
    # action for QGIS 2/PyQt4

これは、一部の孤立したものでは機能する場合がありますが、一般的なソリューションとしては機能しない場合があります。
マティアスクーン

1

QGIS Pythonプラグインの移植が終了したので、2.xと3.xの両方のQGISバージョンをサポートするようになりました。私の経験は次のとおりです。

ほとんどの場合、QGISバージョンに依存しようとしました。しかし、バージョンを保持するクラスでさえ少し名前が変更されました。だから最初にやった

try:
    from qgis.utils import Qgis  # for QGIS 3
except ImportError:
    from qgis.utils import QGis as Qgis  #  for QGIS 2

そして、チェックを行います

if Qgis.QGIS_VERSION >= '3.0':
    # something for QGIS 3
else:
    # something for QGIS 2

最終バージョンをデプロイした後、resources.py自動的に作成されるファイルpyrcc5も移植する必要があることに気付きました。そうしないと、プラグインは2.xで壊れ続けます。だから私はその行を変更しました

from PyQt5 import QtCore

try:
    from PyQt5 import QtCore
except:
    from PyQt4 import QtCore

うまくいったようです。私は公式リリースを作成し、それだと思いました。それから私はこのシーケンスを発見しました:

プラグインをQGIS 2.18にインストールし、QGISを閉じ、QGISを開き、QGIS内でPythonコンソールを開きます-> QGIS全体が即座にクラッシュします!

いくつかのテストを行った結果、resources.py上記の小さな変更が原因であることがわかりました。私はQGIS Pythonライブラリの専門家ではありませんが、私の説明は次のとおりです。

QGISを開くと、プラグインが初期化されます。やろうとする試みfrom PyQt5 import QtCoreすると、間違ったバージョンのPyQtが例外を発生させる前に、QGISの「ワークフロー」にいくつかの変更が発生します(これはRuntimeError)。Pythonコンソールを起動すると、これらの変更によりQGISがクラッシュします。

最後に、私は別のソリューションを決定しました。QGIS 2はPython 2.7を使用し、QGIS 3はPython 3を使用するため常にPythonバージョンをチェックするだけです。ます。

from sys import version_info

if version_info[0] >= 3:
    # something for QGIS 3
else:
    # something for QGIS 2

これにより、潜在的に有害なすべてのインポート試行が回避されます。現在、私のプラグインは両方のQGISバージョンで問題なく動作します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.