Reputation: 744
I am wanting to use a simple list comprehension to set __all__
for the modules in my package. I am noticing that when I import something from one of my own modules that the module name is added to the namespace, not just what I am importing. This is not the same when as when importing builtin or third-party packages.
- foo
- __init__.py
- bar.py
- baz.py
__init__.py
import os as _os
from numpy.random import randint as _randint
import foo.bar as _bar
from foo.baz import foobar
__all__ = [x for x in globals() if not x.startswith('_')]
I expect:
>>> import foo
>>> foo.__all__
['foobar']
But I get:
>>> import foo
>>> foo.__all__
['bar', 'baz', 'foobar']
I know I could expand my list comprehension for __all__
to filter out ModuleType
but I am wondering why the behavior is different for my own modules. I would really like to be able to use a leading underscore to handle this as I can with other packages. I have also tried using dir()
, locals()
, and vars()
instead of globals()
but the result is the same.
Update
Out of curiosity, I also imported foobar
into bar.py
and printed globals()
and 'bar'
was not included. So, it appears my modules are only added to the namespace within __init__.py
files?
Upvotes: 1
Views: 820
Reputation: 32153
All credits to @MisterMiyagi in comments.
I will only confirm this with a quote from the official documentation 5.4.2. Submodules:
When a submodule is loaded using any mechanism [...] a binding is placed in the parent module’s namespace to the submodule object.
For example in your case, if package foo
has a submodule bar
, after importing foo.bar
, foo
will have an attribute bar
which is bound to the submodule foo.bar
.
Upvotes: 1