Зробити плагін QGIS python для обох версій 2.x та 3.x?


12

Я переношу плагін QGIS python з QGIS 2на QGIS 3та переглядаю різні ресурси.

Незрозуміло, чи можливо плагін сумісний з обома версіями або якщо для плагіна потрібні дві ручки.

Наразі проблема, якою я потрапила, полягає в тому, як керувати імпортом PyQt (PyQt4 / PyQt5)?

Відповіді:


18

Документація

Тут ви можете дізнатися про те, що є новим і що є перервою в API PyQGIS .
Щоб отримати детальну інформацію про те, як перенести Python2 на Python3, перейдіть туди

Ви можете знайти детальну інформацію про тестування від QGIS2 до QGIS3 з цього питання: Написання автоматизованих тестів для QGIS плагінів?

Тут ви знайдете цікавий документ OpenGis.ch про інструменти міграції.

Що зміниться в моєму коді

Насправді вам потрібно змінити код плагіна, який не готовий пройти через нову версію.

Ви отримуєте функцію qgis.utils.QGis.QGIS_VERSION_INT, яка створена для перевірки версії QGIS. Це корисно, коли функцію припинено. Для прикладу setSelectedFeaturesз 2.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 підтримує лише новий стиль сигналу та слоти handlig. Виклики на SIGNAL () або SLOT () більше не підтримуються. PyQt5 не підтримує жодної частини API Qt, яка в Qt v5.0 позначена як застаріла або застаріла.

джерело: ( http://zetcode.com/gui/pyqt5/introduction/ )

Ось кілька прикладів змін у вашій заяві from / import:

Пам'ятайте, що з PyQt4 вам потрібно було подивитися на документ API:
для
прикладу модуля
QQ Qore 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:
PyQt5 QtCore модуль
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 ). Розробники додатків зазвичай використовують це з API вищого рівня, наприклад, що містяться в модулі QtWidgets.

А PyQt5 підтримує лише новий стиль сигналу та слоти handlig! поглянути на цю сторінку , щоб зрозуміти , як використовувати pyqtSignal, connectі 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

І не забувайте, що вам також потрібно змінити якусь конкретну функцію під вашим кодом, додавши операцію спробувати / за винятком або якщо if.


2
Великий відповідь, що - то , що буде в значній мірі допомоги в першу замінити будь-якого from PyQt4.QtCore import *з from PyQt4.QtCore import QSomething, QWhatever, QElse, це не зробить сценарій міграції зробити останній крок належним чином ( в тому числі необхідних коригувань , де змінені модулі), тому немає примірочних , крім імпорту необхідні.
Маттіас Кун

ви праві, я використовував *, щоб зробити це просто, але я зміню це, дякую за ваш відгук
Hugo Roussaffa - GeoDatup

ця тема - ідеальне місце, щоб сказати людям не використовувати * -імпорт, адже тут насправді це має значення
Маттіас Кун

@Hugo: Справді, дуже детальна відповідь, вона дуже допомогла почати. Я додамо плагін qgis2compat до численних вже використаних ресурсів.
sigeal

Це чудова ідея. Ви можете редагувати відповідь, як хочете. Дякуємо за відгук
Hugo Roussaffa - 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 agan, а потім відкрийте консоль Python всередині QGIS -> Весь QGIS миттєво вийде з ладу!

Після деякого тестування я з'ясував, що причиною стала ця невелика зміна resources.pyнаписаного вище. Я не є експертом у бібліотеках QGIS Python, але моє пояснення таке:

Коли я відкриваю QGIS, мій плагін ініціалізується. Спроба зробити це from PyQt5 import QtCoreвикликає деякі зміни у "робочому процесі" QGIS, перш ніж неправильна версія PyQt викликає виняток (це було a 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 без проблем.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.