How can you easily select between PyQt or PySide a

2019-02-17 14:58发布

问题:

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.

回答1:

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 *


回答2:

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'>


回答3:

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 *