How can you easily select between PyQt or PySide at runtime? - python

I would like to do something like this in one source file, QT.py:
import sys
import PyQt4
sys.modules["Qt"] = PyQt4
Then import this file in the other source files, and use it like this:
import QT
from Qt.QtCore import *
So I can change from PyQt4 to PySide in QT.py without touching all the source files (with a possibly ugly sed script)
These modules are mostly API compatibile and I would like to test them both. Is there an easy way to do this? (Because the ways I tried are not working)
Maybe the I need imp module, but it seems too low level.
Any ideas?

Use an import hook:
def set_qt_bindings(package):
if package not in ('PyQt4', 'PySide'):
raise ValueError('Unknown Qt Bindings: %s' % package)
import __builtin__
__import__ = __builtin__.__import__
def hook(name, globals=None, locals=None, fromlist=None, level=-1):
root, sep, other = name.partition('.')
if root == 'Qt':
name = package + sep + other
return __import__(name, globals, locals, fromlist, level)
__builtin__.__import__ = hook
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
set_qt_bindings(sys.argv[-1])
import Qt
print Qt
from Qt import QtCore
print QtCore
from Qt.QtGui import QWidget
print QWidget
Output:
$ python2 test.py PySide
<module 'PySide' from '/usr/lib/python2.7/site-packages/PySide/__init__.py'>
<module 'PySide.QtCore' from '/usr/lib/python2.7/site-packages/PySide/QtCore.so'>
<type 'PySide.QtGui.QWidget'>
$ python2 test.py PyQt4
<module 'PyQt4' from '/usr/lib/python2.7/site-packages/PyQt4/__init__.pyc'>
<module 'PyQt4.QtCore' from '/usr/lib/python2.7/site-packages/PyQt4/QtCore.so'>
<class 'PyQt4.QtGui.QWidget'>

update: Figured out method more in line with your requirements:
You can structure your pseudo-module as:
Qt/
Qt/__init__.py
Qt/QtCore/__init__.py
Qt/QtGui/__init__.py
Where Qt/__init__.py is:
import QtCore, QtGui
Qt/QtCore/__init__.py is:
from PyQt4.QtCore import *
Qt/QtGui/__init__.py is:
from PyQt4.QtGui import *
Then, in your code, you can reference it as follows:
import sys
from Qt import QtGui
app = QtGui.QApplication(sys.argv)
from Qt.QtGui import *
window = QWidget()
window.show()
app.exec_()
I highly recommend against using from Qt.QtGui import * in your code as importing everything is considered bad form in Python since you lose all namespaces in the process.
update:
I like Ryan's suggestion of conditional imports. I'd recommend combining that into the above code. For example:
Qt/QtGui/__init__.py:
import sys
if '--PyQt4' in sys.argv:
from PyQt4.QtGui import *
else:
from PySide.QtGui import *

You can conditionally import libraries. Here is a bit of a hacky example, where you check for a command-line argument of "PyQt4":
import sys
if sys.argv[-1] == 'PyQt4':
import PyQt4
sys.modules["Qt"] = PyQt4
else:
import Qt
from Qt.QtCore import *

Related

shiboken2, ImportError: DLL load failed: The specified procedure could not be found

I had a PyQT Project which was working very well 1-2 months ago. I made some changes (not in the PyQT Project, but in other python files in same directory) and then ran the same PyQT Project again, but now it is giving me error.
The error is as follows,
PySide2/__init__.py: Unable to import shiboken2 from e:\Programming\PyQT\Second_Project,
At the end of the error, I found this ImportError,
ImportError: DLL load failed: The specified procedure could not be found.
I have tried lots of things but still I could not find any solution to this. I tried to re-install the PySide2 but to no use. I tried to change my Python Interpreter from 3.6.0 to 3.8.6 and also 3.9.2 but again, I got the same error. I also tried other different things answered in various Stackoverflow posts but nothing has seemed to work for me.
Can anyone help me how do I resolve this? I am 100% sure that the changes I made in other python files have absolutely nothing to do with this PyQT Project and this problem did not occur because of those changes.
The lines on which I got errors are,
from PySide2 import shiboken2 # Added this line later because shiboken2 wasn't being imported, but still it did not work
import iconify as ico
from iconify.qt import QtGui as IconQtGui, QtWidgets as IconQtWidgets
import PySide2
All the imports that I am making in my main.py file,
import sys
import os
from PyQt5.sip import delete
from PySide2 import shiboken2
# import iconify as ico
from iconify.qt import QtGui as IconQtGui, QtWidgets as IconQtWidgets
import PySide2
import mysql.connector as mc
from qt_material import *
# from PyQt5 import QtWidgets, uic, QtGui
from functools import partial
# from PyQt5.QtCore import Qt
from registered_courses import reg_data
from add_section_page import Ui_Add_Section_Window
from edit_section_page import Ui_Edit_Section_Window
from add_course_page import Ui_Add_Course_Window
from edit_course_page import Ui_Edit_Course_Window
from add_room_page import Ui_Add_Room_Window
from edit_room_page import Ui_Edit_Room_Window
from add_teacher_page import Ui_Add_Teacher_Window
from edit_teacher_page import Ui_Edit_Teacher_Window
from add_registered_course import Ui_Add_Registered_Course_Window
from edit_registered_course import Ui_Edit_Registered_Course_Window
from registered_section_student_details import Ui_Registered_Section_Students_Window
from add_section_student_page import Ui_Add_Section_Student_Window
from add_room_preferences import Ui_Add_Room_Preferences_Teacher_Window
from add_slot_preferences import Ui_Add_Slot_PReferences_Teacher_Window
import sections_timetable
import rooms_timetable
import teachers_timetable
from time_table import *
from student_clashes import *
from teacher_clashes import *
from room_clashes import *
from stylesheet import *
from util import *
#####################################
# Import GUI File
from ui_interface import *
Also, these are all the imports that are being made in my ui_interface file (the python file that is being generated by the Qt Designer)
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'interfaceGufDiZ.ui'
##
## Created by: Qt User Interface Compiler version 5.14.1
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
QRect, QSize, QUrl, Qt)
from PySide2.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont,
QFontDatabase, QIcon, QLinearGradient, QPalette, QPainter, QPixmap,
QRadialGradient)
from PySide2.QtWidgets import *
import icons_rc

How to determine what to import for, for example, the matchFlags used with QTreeWidget.findItems?

I am trying to use function QTreeWidget.findItems to find an exact match (the item is named "Things")
I saw an example using this ... Qt.MatchExactly ... as the 'match flag'.
even though i had imported Qt module from PyQt5, the MatchExactly was not found.
I got it to work by importing ANOTHER Qt module found in QtCore in PyQt5. but that was after many hours over several days of poking, guessing, and reading stackOverFlow posts.
My question is - how to know what module contains (and therefore must be imported) the stuff I need? how would I know that Qt.MatchExactly is in the PyQt5.QtCore.Qt module (and NOT in PyQt5.Qt module)?
This is my code: Note it reads in a QtDesigner .ui file, so its not gonna work for you. but having you run this code is not the point.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import QMainWindow, QApplication, QTreeWidgetItem
from PyQt5 import uic, QtWidgets, Qt #<<flags are not here
from PyQt5 import QtCore
from PyQt5.QtCore import Qt #<<<this is where i found the match flag "MatchExactly"
qtCreatorFile = "Main2.ui" # Enter qt Designer file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class MyApp(QMainWindow):
def __init__(self):
super(MyApp, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.InitModelContentTree()
def InitModelContentTree (self):
modelContentTree = self.ui.ModelContentTree
ThingsItemList = modelContentTree.findItems("Things", Qt.MatchExactly)
ThingsItem = ThingsItemList[0]
QTreeWidgetItem(ThingsItem, ["New Thing"])
print("pause")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
i'm hoping there is a decoder ring, some basic thing i'm missing. i'm proving to be a very bad, very inefficient guesser.
Actually Qt.MatchExactly is in Qt but you must import it in another way:
from PyQt5 import Qt
# ...
ThingsItemList = modelContentTree.findItems("Things", Qt.Qt.MatchExactly)
TL; DR
The Qt submodule is a fake module that allows access to any module such as an alias, for example it is similar to:
from PyQt5 import QtCore as Qt
from PyQt5 import QtGui as Qt
from PyQt5 import QtWidgets as Qt
# ...
# The same for all submodules
For example it can be checked for Qt.MatchExactly:
from PyQt5 import Qt, QtCore
assert(QtCore.Qt.MatchExactly == Qt.Qt.MatchExactly)
So in general the following import:
from PyQt5 import somemodule
somemodule.someclass
It is equivalent to:
from PyQt5 import Qt
Qt.someclass
How to know what submodule a class belongs to?: Well, if you have an IDE that can do a self-report like pycharm, the task is simple since the IDE itself does it. But if I do not have access to the IDE the other option is to use the docs of Qt, for example the docs of Qt::MatchExactly is in this link that in the first part is the following table:
And observe Qt += core so all the elements of that docs belong to the core sub-module of Qt that in PyQt/PySide corresponds to QtCore (in general if the docs of Qt indicate Qt += mymodule in PyQt/PySide in QtMyModule).Also the Qt::MatchExactly of C ++ corresponds to Qt.MatchExactly in python. So in conclusion you should use:
from PyQt5 import QtCore
QtCore.Qt.MatchExactly

In a PySide2 app, how can I get the ID for a QWindow?

In the version of PySide2 that ships with Maya2017, the winId method on the QWindow class seems to be missing:
w.winId()
Error: AttributeError: file <maya console> line 1: 'PySide2.QtGui.QWindow' object has no attribute 'winId' #
Is there a way to get this value from an existing instance of QWindow?
I used Maya 2018 for macOS 10.11.6. Try this code. It works.
from maya import OpenMayaUI as omui
try:
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from PySide2 import __version__
from shiboken2 import wrapInstance
except ImportError:
from PySide.QtCore import *
from PySide.QtGui import *
from PySide import __version__
from shiboken import wrapInstance
mayaMainWindowPtr = omui.MQtUtil.mainWindow()
mayaMainWindow= wrapInstance(long(mayaMainWindowPtr), QWidget)
w = QLabel("Hello, Window", parent=mayaMainWindow)
w.setObjectName('Label1')
w.setWindowFlags(Qt.Window)
w.show()
And after typing:
w.winId()
you'll get something like this:
# Result: 140640756092816 #
Andy's example works for me in both Maya2018 and the latest release of Maya2017, but throws an exception in at least the initial release of Maya 2017.
I expect the problem was caused by a bug in PySide2 that got fixed along the way.

Imported module but still need to use full name

I've been able to successfully import QtWidgets from PyQt5 and this works fine in code however if I don't use the full QtWidgets name in the call I get an error. Below works...
import sys
from PyQt5 import QtWidgets
app = QtWidgets.QApplication(sys.argv)
Yet if do...
import sys
from PyQt5 import QtWidgets
app = QApplication(sys.argv)
I get ...
NameError: name 'QApplication' is not defined
Your misunderstanding how Python import statements work. When importing a module in Python, only the module directly imported is include in the local symbol table.
Thus, if you have not directly imported a name, it cannot be used as a standalone identifier in the current namespace. If you want this behavior, directly import the QApplication name from the QtWidgets namespace:
from PyQt5.QtWidgets import QApplication
Import modules like this:
import sys
from PyQt5.QtWidgets import *
app = QApplication(sys.argv)

PyQT5 with dbus interface freezes on interspection (where PyQT4 works)

I have a following simple snippet which works on PyQT4:
from PyQt4.QtCore import QCoreApplication
import math
import dbus
import dbus.service
from dbus.mainloop.qt import DBusQtMainLoop
class Calculator(dbus.service.Object):
def __init__(self):
busName = dbus.service.BusName('org.calc.Calculator', bus = dbus.SessionBus())
dbus.service.Object.__init__(self, busName, '/Calculator')
#dbus.service.method('org.calc.Calculator', in_signature = 'dd', out_signature = 'd')
def add(self, a, b):
return a+b
DBusQtMainLoop(set_as_default = True)
app = QCoreApplication([])
calc = Calculator()
app.exec_()
however, if I substitute the PyQT4 import for a PyQT5 one:
from PyQt5.QtCore import QCoreApplication
the application hangs on interspection.
Any ideas how to fix this? More imporantantly, what may be the cause?
Turns out with PyQt5 you need to use PyQt5 specific dbus module providing the mainloop:
from dbus.mainloop.pyqt5 import DBusQtMainLoop
instead of:
from dbus.mainloop.qt import DBusQtMainLoop

Categories