7

我是新手,刚开始学习 Python 编程:

import sys
from PyQt5 import QtWidgets

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    mainWindow = QtWidgets.QMainWindow()
    mainWindow.show()

    sys.exit(app.exec_())

当我运行上面的代码时,一切正常。但是当我运行下面的代码时,它失败并显示以下错误消息:app = PyQt5.QtWidgets.QApplication(sys.argv) AttributeError: 'module' object has no attribute 'QtWidgets'

import sys
import PyQt5
if __name__ == "__main__":
    app = PyQt5.QtWidgets.QApplication(sys.argv)

    mainWindow = PyQt5.Qtwidgets.QmainWindow()
    mainWindow.show()

    sys.exit(app.exec_())

顺便说一句,我的 Python 版本是 2.7,我使用的是 Qt5 库,我的操作系统是 OpenSUSE 13.2,当然是 Linux 的发行版。

4

2 回答 2

1

Qtwidgets文件是目录中的编译.so文件,PyQt5所有模块也是如此,文件中没有导入,__init__.py因此您需要使用 from ...

在空test1.cpython-34m.so目录中 使用 cython 编译文件的示例表现出相同的行为:py3__init.__py

In [1]: import py3

In [2]: py3.test1
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-2-9aa45b2a49b6> in <module>()
----> 1 py3.test1

AttributeError: 'module' object has no attribute 'test1'

In [3]: from py3 import test1
In [4]: test1.foo()
Out[4]: 100

PyQt5中的文件如下:

/usr/lib/python3/dist-packages/PyQt5$ ls
__init__.py
__pycache__
_QOpenGLFunctions_2_0.cpython-34m-x86_64-linux-gnu.so
QtCore.cpython-34m-x86_64-linux-gnu.so
Qt.cpython-34m-x86_64-linux-gnu.so
QtDBus.cpython-34m-x86_64-linux-gnu.so
QtDesigner.cpython-34m-x86_64-linux-gnu.so
QtGui.cpython-34m-x86_64-linux-gnu.so
QtHelp.cpython-34m-x86_64-linux-gnu.so
QtNetwork.cpython-34m-x86_64-linux-gnu.so
QtOpenGL.cpython-34m-x86_64-linux-gnu.so
QtPrintSupport.cpython-34m-x86_64-linux-gnu.so
QtTest.cpython-34m-x86_64-linux-gnu.so
QtWidgets.cpython-34m-x86_64-linux-gnu.so
uic

使用cat你可以看到没有导入__init__.py

$:/usr/lib/python3/dist-packages/PyQt5$ cat __init__.py 
# Copyright (c) 2014 Riverbank Computing Limited <info@riverbankcomputing.com>
# 
# This file is part of PyQt5.
# 
# This file may be used under the terms of the GNU General Public License
# version 3.0 as published by the Free Software Foundation and appearing in
# the file LICENSE included in the packaging of this file.  Please review the
# following information to ensure the GNU General Public License version 3.0
# requirements will be met: http://www.gnu.org/copyleft/gpl.html.
# 
# If you do not wish to use this file under the terms of the GPL version 3.0
# then you may purchase a commercial license.  For more information contact
# info@riverbankcomputing.com.
# 
# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 

__init__.py 因此,因为在您尝试使用时没有导入,所以PyQt5.Qtwidgets您会看到错误,因为模块显然没有属性。

如果您添加了类似from . import QtWidgets的东西,那么您可以在从__init__.py中导入模块时使用import PyQt5 PyQt5.Qtwidgets或者PyQt5.Qtwidgets也可以使用空白 init 。Qtwidgets PyQt5

您可以看到当您import PyQt5实际上有一个模块时:

In [6]: import PyQt5

In [7]: type(PyQt5)
Out[7]: module

因此,真正的区别以及您看到输出的原因是您尝试从第二个示例中的模块和第一个示例中的导入。

于 2015-03-17T21:06:12.667 回答
1

PyQt5部分只是为一组模块提供了一个命名空间。它本身不包含任何内容,因此您不能直接从中导入任何内容。

这是一个深思熟虑的设计决定,这样做是有充分理由的。包中可能总共有三十个或更多模块,因此每次导入时PyQt5加载它们将是一笔沉重的前期成本。因此,我们的目的是只支付加载您实际需要的模块的成本。

但是,有时您确实想一次加载所有模块。例如,在 python 交互式会话中进行实验时能够做到这一点会非常方便。事实上,PyQt 提供了一个特殊的模块来做这件事:

>>> from PyQt5 import Qt
>>> Qt.QWidget
<class 'PyQt5.QtWidgets.QWidget'>
>>> Qt.QObject
<class 'PyQt5.QtCore.QObject'>
>>> Qt.QNetworkCookie
<class 'PyQt5.QtNetwork.QNetworkCookie'>
于 2015-03-17T23:41:13.930 回答