Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: how to import from all modules in dir?

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.

like image 467
ov7a Avatar asked May 31 '13 08:05

ov7a


People also ask

How do I import an entire module?

You need to use the import keyword along with the desired module name. When interpreter comes across an import statement, it imports the module to your current program. You can use the functions inside a module by using a dot(.) operator along with the module name.

How does Python import modules from some other directory?

We can use sys. path to add the path of the new different folder (the folder from where we want to import the modules) to the system path so that Python can also look for the module in that directory if it doesn't find the module in its current directory.


1 Answers

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.

like image 184
Blender Avatar answered Sep 19 '22 13:09

Blender