【问题标题】:How can you easily select between PyQt or PySide at runtime?如何在运行时轻松地在 PyQt 或 PySide 之间进行选择?
【发布时间】:2011-12-24 12:59:36
【问题描述】:

我想在一个源文件 QT.py 中做这样的事情:

import sys
import PyQt4

sys.modules["Qt"] = PyQt4

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

import QT
from Qt.QtCore import *

所以我可以在 QT.py 中从 PyQt4 更改为 PySide 而无需触及所有源文件(使用可能丑陋的 sed 脚本) 这些模块大多是 API 兼容的,我想同时测试它们。是否有捷径可寻? (因为我试过的方法都行不通)

也许我需要imp 模块,但它似乎太低级了。

有什么想法吗?

【问题讨论】:

    标签: python pyqt pyside python-module


    【解决方案1】:

    使用导入钩子:

    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 *
      

      【讨论】:

      • 我不确定是否要向项目中添加空的伪模块。特别是因为 PySide/PyQt 包含更多的子模块。
      • @Guttalax 你说这是为了测试,对吧?我不想在生产环境中做这样的事情。如果您在生产环境中这样做,请不要import *。没有它,你可以做一些像Qt/__init__.py 这样简单的事情,其中​​__init__.pyfrom PyQt4 import *。然后你可以引用Qt.QtGui.QWidget()
      • 嗯,是的,它是用于测试的。你看,这是我的一个爱好项目,我不介意有点骇人听闻的解决方案。理想情况下,我想为其他人提供一种在 pyside 和 pyqt 之间切换的简单方法,或者甚至让程序使用任何可用的方法。
      【解决方案3】:

      您可以有条件地导入库。这是一个 hacky 示例,您可以在其中检查“PyQt4”的命令行参数:

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

      【讨论】:

        猜你喜欢
        • 2010-12-18
        • 2010-10-17
        • 2014-08-30
        • 1970-01-01
        • 2013-10-07
        • 1970-01-01
        • 2017-11-23
        • 2015-12-28
        • 2012-01-26
        相关资源
        最近更新 更多