Reputation: 83
I would like to import all modules inside a package as aliases in __main__ using __init__.py so they can be called simply from interactive mode. For example, here is a sample file tree:
foobar/
__init__.py
foo.py
bar.py
and from the python interpreter I want to be able to import the package and have access to all modules using defined aliases like this:
>>> import foobar
>>> <module 'foobar' from 'C:\...'>
>>> f.func()
>>> b.func()
This will require __init__.py to contain something along the lines of:
# __init__.py
from . import foo as f
from . import bar as b
# these will not work
__main__.f = f
__main__.b = b
How can I make this work?
EDIT
I don't want to use from foobar import *
because it will not allow me to use aliasing.
Typing from foobar import foo as f
for every module, every time I start interactive mode is not efficient because there could be hundreds of modules.
Upvotes: 2
Views: 3819
Reputation: 25833
In your __init__.py file include something like:
import foo
import bar as b
Then in the interactive session use:
>>> from foobar import *
>>> value = foo.some_func()
>>> instance = b.SomeClass()
I should also mention that from foobar import *
is considered bad style by most python programers, and while that doesn't matter in an interactive session, if you wanted to accomplish the same thing in a module or script the preferred way would be:
from foobar import b, foo
Upvotes: 3
Reputation: 104762
It would be very bad behavior for a module to add things to a separate module's namespace without being explicitly told to do so. Explicit is better than implicit, as they say.
I suggest you avoid anything complicated in your __init__.py
and simply do this in your main module (or on the command line):
import foobar.foo as f, foobar.bar as b
Edit:
It is possible to mess around with the main module if you really need to. While it's probably not a good idea, here's how:
import sys
import foo, bar
main = sys.modules["__main__"]
main.f = foo
main.b = bar
Now, as several people have said, its usually not a good idea to make importing a module have side effects like that. At the very least, anyone else who ever reads your code will be tremendously confused. "Wait, where did this f
variable come from?"
Instead of making your module insert things into your global namespace, what I suggest is that you have it do the aliasing you want in its own namespace, and then use from module import *
on it to get the aliases in your namespace.
Make foobar
's __init__.py
file look like this:
from . import foo as f
from . import bar as b
Then in your main module, just do:
from foobar import *
# now you can use f and b
If you have hundreds of imports to do, put them all in __init__.py
. Or if they're not associated with that package, use a separate module to handle the aliasing stuff.
Upvotes: 1
Reputation: 8244
It is simply not designated for a Python module to break out of its namespace like that and, because Python effectively tends to restrict everything that is generally not a good idea, it wouldn't be possible. The interactive console might have something like startup hooks, who knows.
Another idea that could make life easier for you: Write into the module:
foo = "foo!"
bar = "bar!"
def add_to(obj):
obj['f'] = foo
obj['b'] = bar
In your interactive console:
>>> from stuff import add_to
>>> add_to(globals())
Upvotes: 0