Відповіді:
Тут ви можете дізнатися про те, що є новим і що є перервою в 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 ТА також код для перевірки версії та можливостей імпорту нових бібліотек).
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.
Спробуйте щось подібне:
try:
# action for QGIS 3/PyQt5
except:
# action for QGIS 2/PyQt4
Я щойно закінчив переносити плагін 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 без проблем.
from PyQt4.QtCore import *
зfrom PyQt4.QtCore import QSomething, QWhatever, QElse
, це не зробить сценарій міграції зробити останній крок належним чином ( в тому числі необхідних коригувань , де змінені модулі), тому немає примірочних , крім імпорту необхідні.