85

I have a directory with a number of .py files in it. each file defines some classes. I also have an empty __init__.py in the directory.

For example:

myproject
    __init__.py
    mymodule
        __init__.py
        api.py
        models.py
        views.py

I am trying to import mymodule and access the classes defined in all these files:

from myproject import mymodule

print mymodule.api.MyClass 

It gives me an error saying that mymodule has no attribute api. Why? And why I can access just one of the files (models.py) and not the others?

In [2]: dir(banners)
Out[2]:
['__builtins__',
 '__doc__',
 '__file__',
 '__name__',
 '__package__',
 '__path__',
 'models']
BorrajaX
  • 15,678
  • 13
  • 76
  • 122
akonsu
  • 27,402
  • 26
  • 115
  • 185

4 Answers4

88

The problem is submodules are not automatically imported. You have to explicitly import the api module:

import myproject.mymodule.api
print myproject.mymodule.api.MyClass

If you really insist on api being available when importing myproject.mymodule you can put this in myproject/mymodule/__init__.py:

import myproject.mymodule.api

Then this will work as expected:

from myproject import mymodule

print mymodule.api.MyClass 
Rob Wouters
  • 14,819
  • 2
  • 40
  • 36
  • 1
    hi, i tried this but i still get a ModuleNotFoundError: No module named lib.myfunction. any thoughts? the funny thing is if i just import lib, there is no error. if i call lib.myfunction after that it also throws an error. – yl_low Apr 10 '18 at 11:26
  • Isn't this a bit cumbersome? Is there a way to switch on importing of sub-modules (with the full qualifying names, e.g foo.bar.baz) by default? – Amir Rosenfeld May 01 '19 at 15:20
  • I'm fine doing the full import, but in the rest of the code I'd like to drop `myproject` and refer to `mymodule.api` which does not seem to be possible? – Alper Aug 16 '19 at 10:03
21

If you are an idiot, like me, then also check whether you didn't name your python file the same as the module you are trying to import.

Olaf
  • 349
  • 2
  • 5
0

Modules don't work like that.

from myproject.mymodule import api
print api.MyClass
Daniel Roseman
  • 567,968
  • 59
  • 825
  • 842
  • I know I can do that. Is it possible to do using the dotted names? – akonsu Jan 17 '12 at 17:47
  • 2
    @akonsu, simply do `import myproject.mymodule.api` then and access it through `myproject.mymodule.api.MyClass`. – Rob Wouters Jan 17 '12 at 17:50
  • well, i think this is a question about the language in general, not about how I can get my code to work. I am curious as to whether this can be achieved. can I make it access my classes through 'mymodule.api...' without the leading 'myproject'? – akonsu Jan 17 '12 at 17:53
  • you could do `import myproject.mymodule as mymodule` but it seems confusing to me – Matt Jan 17 '12 at 18:00
-1

You need an __init__.py in the myproject directory too. So your module structure should be:

myproject
    __init__.py
    mymodule
        __init__.py
        api.py
        models.py
        views.py
Akash
  • 283
  • 2
  • 11