Reputation: 58791
I have a Python module with the following structure:
mymod/
__init__.py
tools.py
# __init__.py
from .tools import foo
# tools.py
def foo():
return 42
Now, when import mymod
, I see that it has the following members:
mymod.foo()
mymod.tools.foo()
I don't want the latter though; it just pollutes the namespace.
Funnily enough, if tools.py
is called foo.py
you get what you want:
mymod.foo()
(Obviously, this only works if there is just one function per file.)
How do I avoid importing tools
? Note that putting foo()
into __init__.py
is not an option. (In reality, there are many functions like foo
which would absolutely clutter the file.)
Upvotes: 4
Views: 1875
Reputation: 1318
Try putting this in your __init__.py
file:
from .tools import foo
del tools
Upvotes: 0
Reputation: 13046
You are not importing the tools
module, it's just available when you import the package like you're doing:
import mymod
You will have access to everything defined in the __init__
file and all the modules of this package:
import mymod
# Reference a module
mymod.tools
# Reference a member of a module
mymod.tools.foo
# And any other modules from this package
mymod.tools.subtools.func
When you import foo
inside __init__
you are are just making foo
available there just like if you have defined it there, but of course you defined it in tools
which is a way to organize your package, so now since you imported it inside __init__
you can:
import mymod
mymod.foo()
Or you can import foo
alone:
from mymod import foo
foo()
But you can import foo
without making it available inside __init__
, you can do the following which is exactly the same as the example above:
from mymod.tools import foo
foo()
You can use both approaches, they're both right, in all these example you are not "cluttering the file" as you can see accessing foo
using mymod.tools.foo
is namespaced so you can have multiple foo
s defined in other modules.
Upvotes: 0
Reputation: 281277
The existence of the mymod.tools
attribute is crucial to maintaining proper function of the import system. One of the normal invariants of Python imports is that if a module x.y
is registered in sys.modules
, then the x
module has a y
attribute referring to the x.y
module. Otherwise, things like
import x.y
x.y.y_function()
break, and depending on the Python version, even
from x import y
can break. Even if you don't think you're doing any of the things that would break, other tools and modules rely on these invariants, and trying to remove the attribute causes a slew of compatibility problems that are nowhere near worth it.
Trying to make tools
not show up in your mymod
module's namespace is kind of like trying to not make "private" (leading-underscore) attributes show up in your objects' namespaces. It's not how Python is designed to work, and trying to force it to work that way causes more problems than it solves.
The leading-underscore convention isn't just for instance variables. You could mark your tools
module with a leading underscore, renaming it to _tools
. This would prevent it from getting picked up by from mymod import *
imports (unless you explicitly put it in an __all__
list), and it'd change how IDEs and linters treat attempts to access it directly.
Upvotes: 4