Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why it failed without import in python

I am a newbie and am just starting to learn Python programming:

import sys
from PyQt5 import QtWidgets

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

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

    sys.exit(app.exec_())

When I run the above code, every is OK. But when I run the code below, it fails with the following error message: 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_())

By the way, my Python version is 2.7, I'm using Qt5 library and my operating system is OpenSUSE 13.2, of course, a distribution of Linux.

like image 831
Anudorannador Avatar asked Mar 17 '15 20:03

Anudorannador


2 Answers

The PyQt5 part just provides a namespace for a group of modules. It doesn't contain anything itself, and so you cannot import anything directly from it.

This is a deliberate design decision, and is done for a good reason. There could be a total of thirty or more modules in the package, so it would be a heavy up-front cost to load them all every time PyQt5 itself was imported. So instead, the intention is to only pay the cost of loading the modules you actually need.

However, there may be times when you do want to load all the modules at once. For instance, it would be very convenient to be able to do this when experimenting in a python interactive session. And in fact, PyQt provides a special module that does exactly that:

>>> from PyQt5 import Qt
>>> Qt.QWidget
<class 'PyQt5.QtWidgets.QWidget'>
>>> Qt.QObject
<class 'PyQt5.QtCore.QObject'>
>>> Qt.QNetworkCookie
<class 'PyQt5.QtNetwork.QNetworkCookie'>
like image 76
ekhumoro Avatar answered Nov 05 '22 04:11

ekhumoro


The Qtwidgets file is a compiled .so file in the PyQt5 directory, as are all the modules, there are no imports in the __init__.py file so you need to use from ...

An example using a cython compiled file test1.cpython-34m.so in a directory py3 with an empty __init.__py exhibits the same behaviour:

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

The files in PyQt5 are as below:

/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

Using cat you can see that there are no imports in __init__.py:

$:/usr/lib/python3/dist-packages/PyQt5$ cat __init__.py 
# Copyright (c) 2014 Riverbank Computing Limited <[email protected]>
# 
# 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
# [email protected].
# 
# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 

So because there are no imports in the __init__.py when you try to use PyQt5.Qtwidgets you get the error you see as the module obviously has no attributes.

If you added something like from . import QtWidgets to the __init__.py you could then use import PyQt5 PyQt5.Qtwidgets or PyQt5.Qtwidgets would also work with a blank init as you are importing the module Qtwidgets from the package PyQt5.

You can see when you import PyQt5 you then you actually have a module:

In [6]: import PyQt5

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

So the real difference and why you see the output you do is you are trying to import from a module in the second example and a package in the first.

like image 24
Padraic Cunningham Avatar answered Nov 05 '22 05:11

Padraic Cunningham