I want the members of all modules in package to be in package’s
namespace, and I do not want the modules themselves to be in the
namespace.
I was able to do that by adapting something I’ve used in Python 2 to automatically import plug-ins to also work in Python 3.
In a nutshell, here’s how it works:
-
The package’s
__init__.py
file imports all the other Python files in the same package directory except for those whose names start with an'_'
(underscore) character. -
It then adds any names in the imported module’s namespace to that of
__init__
module’s (which is also the package’s namespace). Note I had to make theexample_module
module explicitlyimport foo
from the.foo_module
.
One important aspect of doing things this way is realizing that it’s dynamic and doesn’t require the package module names to be hardcoded into the __init__.py
file. Of course this requires more code to accomplish, but also makes it very generic and able to work with just about any (single-level) package — since it will automatically import new modules when they’re added and no longer attempt to import any removed from the directory.
test.py
:
from package import *
print(example('derp'))
__init__.py
:
def _import_all_modules():
""" Dynamically imports all modules in this package. """
import traceback
import os
global __all__
__all__ = []
globals_, locals_ = globals(), locals()
# Dynamically import all the package modules in this file's directory.
for filename in os.listdir(__name__):
# Process all python files in directory that don't start
# with underscore (which also prevents this module from
# importing itself).
if filename[0] != '_' and filename.split('.')[-1] in ('py', 'pyw'):
modulename = filename.split('.')[0] # Filename sans extension.
package_module=".".join([__name__, modulename])
try:
module = __import__(package_module, globals_, locals_, [modulename])
except:
traceback.print_exc()
raise
for name in module.__dict__:
if not name.startswith('_'):
globals_[name] = module.__dict__[name]
__all__.append(name)
_import_all_modules()
foo_module.py
:
def foo(bar):
return bar
example_module.py
:
from .foo_module import foo # added
def example(arg):
return foo(arg)