Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python import module from a package

folder structure:

<current dir>
   main.py
   packages <dir>
      __init__.py
      mod.py

main py:

import packages
print packages.mod.hello()

mod.py:

def hello():
    return 'hello'

__init__.py:

from packages import mod

If I run main.py, I get no error. But if I edit __init__.py to 'from packages import *' , I get this error: AttributeError: 'module' object has no attribute 'mod'

I'm not asking how to make that 'print' command work. I can use other 'import' syntax in main.py to make it work. The question is: I'm curious about that 'from packages import mod' in the __init__.py. If i can do import mod then when I replace to import *, which means import everything, why do I get an error instead?

So what does the from packages import * really mean inside that __init__.py?

Anyone can help? Thanks

like image 514
andio Avatar asked Apr 09 '16 09:04

andio


1 Answers

Short answer

So what does the from packages import * really mean inside that __init__.py?

The __init__.py imports itself.

Explanation

You can only import modules, not packages. Packages are just containers for modules or sub-packages. When you "import" a package you actually import the module __init__.py.

The __init__.py with this content:

from packages import mod

imports the module mod into __init__.py. Therefore, it will be available in your main.py via packages.mod (remember packages is represented by __init__.py).

When you change the content of __init__.py to:

from packages import *

You are importing the module __init__.py, the very same file you are in. This works (a second import just triggers a lookup in sys.modules) but won't give you the content of mod.

This means, you can use:

from module import *

but you cannot sensibly use this with an empty __init__.py:

from package import *

Because package is actually represented by the __init__.py and there is nothing in it yet. You can check this (interactively or in file):

>>> import packages
>>> print(packages)
<module 'packages' from '/.../packages/__init__.py'>

In __init__.py you can write:

from packages.mod import *

and then in main.py:

print packages.hello()

works. Because the function hello() is now in the global name space of the file __init__.py.

As mentioned in the answer by mozman, you can use __all__ in __init__.py to list the modules that should be imported if from packages import * is used. This is designed for this case.

The __init__.py has only this content:

__all__ = ['mod']

Now you can do this in main.py:

from packages import *

print mod.hello()

If you extend your __init__.py:

__all__ = ['mod']

from packages import *

You can do this in main.py:

import packages

print packages.mod.hello()

But if you remove the from packages import * from __init__.py:

__all__ = ['mod'] 

You will get an error:

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

because the __all__ is only used for the from packages import * case. Now we are back to the __init__.py imports itself.

like image 162
Mike Müller Avatar answered Sep 18 '22 11:09

Mike Müller