如何在运行时轻松选择PyQt或PySide?

5 投票
3 回答
1939 浏览
提问于 2025-04-17 05:52

我想在一个源文件里做一些事情,叫做QT.py:

import sys
import PyQt4

sys.modules["Qt"] = PyQt4

然后在其他源文件中导入这个文件,像这样使用:

import QT
from Qt.QtCore import *

这样我就可以在QT.py里把PyQt4换成PySide,而不需要去改动所有的源文件(也不想用那些可能很麻烦的sed脚本)。这些模块大部分是兼容的,我想同时测试它们。有没有简单的方法可以做到这一点?(因为我尝试过的方法都不行)

也许我需要用到imp模块,但感觉这个太底层了。

有没有什么好主意?

3 个回答

0

你可以根据条件来导入库。这里有一个稍微有点技巧的例子,里面检查了一个命令行参数是否是“PyQt4”:

import sys

if sys.argv[-1] == 'PyQt4':
    import PyQt4
    sys.modules["Qt"] = PyQt4
else:
    import Qt
    from Qt.QtCore import *
4

使用一个导入钩子:

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

输出结果:

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

更新: 我找到了一个更符合你需求的方法:

你可以这样构建你的伪模块:

Qt/
Qt/__init__.py
Qt/QtCore/__init__.py
Qt/QtGui/__init__.py

其中 Qt/__init__.py 是:

import QtCore, QtGui

Qt/QtCore/__init__.py 是:

from PyQt4.QtCore import *

Qt/QtGui/__init__.py 是:

from PyQt4.QtGui import *

然后,在你的代码中,你可以这样引用它:

import sys
from Qt import QtGui
app = QtGui.QApplication(sys.argv)

from Qt.QtGui import *

window = QWidget()
window.show()

app.exec_()

强烈建议不要在你的代码中使用 from Qt.QtGui import *,因为在Python中导入所有内容被认为是不好的做法,这样会导致你失去所有的命名空间。

更新: 我喜欢Ryan关于条件导入的建议。我建议把这个结合到上面的代码中。例如:

Qt/QtGui/__init__.py:

import sys
if '--PyQt4' in sys.argv:
    from PyQt4.QtGui import *
else:
    from PySide.QtGui import *

撰写回答