Importing a large number of modules from a custom package

Say I have this structure.

MyApp ├── main.py └── package ├── __init__.py ├── a.py ├── b.py ├── c.py ├── d.py ├── e.py ├── f.py ├── g.py ├── h.py ├── ... └── z.py 

And in main.py I need to use all modules, from a.py to z.py

I would like to know how I can import all of these modules with a single import statement.

So, instead of doing

 from package import a from package import b ... from package import z 

I could just import the package and prepare all the modules.

What i tried

 import package a = package.aA() # AttributeError: 'module' object has no attribute 'a' 

Now I know that I can put the code in __init__.py to add all the modules to __all__ , but from what I read, we should avoid "from package import"

The reason for this is that a package can have an increasing number of modules, and I would like to add an import statement to the main code every time a module is created. Ideally, I would just leave the module in the package and prepare it for use.

+4
source share
4 answers

In __init__.py you can:

 import a, b, c, d... 

and then the modules will be placed in the package namespace after import package execution.

Do you really want to call a , b , etc. in the main.py namespace, and this will happen effortlessly, you cannot escape from package import * ; any other method of importing them implicitly will be just as bad as it involves polluting the namespace with names that are not explicitly imported.

+4
source

What you offer is a very bad design practice, as you import everything, but not what is required. In general, the SLOW ATTEMPT program - never do this unless it is really required. Never initialize unused variables in modules, as this is a waste of time.

Two solutions that do not comply with good design practice if they are not used correctly.

Check this answer Can anyone explain __all__ in Python? .

You can also use __import__ to load modules and os.path.dirname(__file__) to display all the file names in the directory and load as modules.

By the way, this template leads to serious security holes, because you allow to download everything - this requires only permission to create.

+2
source

I would recommend not to do this. If you need, this is the method I used in the past:

 # __init__.py import os import re PACKAGE = 'MyApp.package' MODULE_RE = r"^.*.py$" for filename in os.listdir(os.path.dirname(__file__)): if not re.match(MODULE_RE, filename) or filename == "__init__.py": continue imported_module = __import__('%s.%s' % (PACKAGE, filename[:-3]), {}, {}, filename[:-3]) 
+2
source

This code is not very pretty, but I think this is a good workaround

 import os for i in os.listdir('package'): if i.endswith('.py') and not i.startswith('__'): exec('from package import ' + i[:-3]) 
+1
source

All Articles