14

Dir structure:

main.py
my_modules/
   module1.py
   module2.py

module1.py:

class fooBar():
    ....
class pew_pew_FooBarr()
    ....
...

How can I add all classes from module* to main without prefixes (i.e. to use them like foo = fooBar(), not foo = my_modules.module1.fooBar()).

An obvious decision is to write in main.py something like this:

from my_modules.module1 import *
from my_modules.module2 import *
from my_modules.module3 import *
...

But I don't want to change main.py when I create new moduleN. Is there solution for that?

I do know it's not a good idea to import classes like this, but I'm still curious about that.

UPD: This question differs from this one Loading all modules in a folder in Python, because my problem is to load modules without namespaces.

Community
  • 1
  • 1
ov7a
  • 1,497
  • 4
  • 15
  • 34
  • 1
    Do you mean Dynamic Module import in python http://stackoverflow.com/questions/301134/dynamic-module-import-in-python ? – Rahul K May 31 '13 at 08:42
  • Dynamic module import is quite complex solution for this, I think. – ov7a May 31 '13 at 12:00

1 Answers1

37

In the my_modules folder, add a __init__.py file to make it a proper package. In that file, you can inject the globals of each of those modules in the global scope of the __init__.py file, which makes them available as your module is imported (after you've also added the name of the global to the __all__ variable):

__all__ = []

import pkgutil
import inspect

for loader, name, is_pkg in pkgutil.walk_packages(__path__):
    module = loader.find_module(name).load_module(name)

    for name, value in inspect.getmembers(module):
        if name.startswith('__'):
            continue

        globals()[name] = value
        __all__.append(name)

Now, instead of doing:

from my_modules.class1 import Stuff

You can just do:

from my_modules import Stuff

Or to import everything into the global scope, which seems to be what you want to do:

from my_modules import *

The problem with this approach is classes overwrite one another, so if two modules provide Foo, you'll only be able to use the one that was imported last.

Blender
  • 289,723
  • 53
  • 439
  • 496
  • can the above code go in __init__.py file or should it go somewhere else so as to automatically import modules. – nish Nov 08 '13 at 09:49
  • Exactly what I wanted. However, `find_module` is deprecated since 3.3. – VPfB Dec 05 '15 at 14:36
  • Thanks so much - I've been looking for a while for THIS portable (zip or module) way to import all modules in a package - this worked perfectly! – Chuck Buche Jul 03 '16 at 01:20
  • A simpler alternative to `loader.find_module(name).load_module(name)` is `importlib.import_module(name)` – llf Jan 04 '19 at 05:51