Package __init__.py Import All Subfiles, But Only Load One From Another Script?
Solution 1:
Here's a way to do something very close what you want. Instead of unconditionally import
ing all the package's classes in your __init__.py
, you can define a function in it to explicitly import any of the ones desired (or all of them if none are specified).
__init__.py
:
from pathlib import Path
import sys
print(f'In {Path(__file__).name}')
package_name = Path(__file__).parent.name
package_prefix = package_name + '.'
class_to_module_map = {'Load': 'load', 'Train': 'train', 'Test': 'test'}
defimport_classes(*class_names):
namespace = sys._getframe(1).f_globals # Caller's globals.ifnot class_names:
class_names = class_to_module_map.keys() # Import them all.for class_name in class_names:
module = class_to_module_map[class_name]
temp = __import__(package_prefix+module, globals(), locals(), [class_name])
namespace[class_name] = getattr(temp, class_name) # Add to caller's namespace.
For testing purposes, here's what I put in the load.py
script:
(I also put something similar in the other two modules in order to verify whether or not they were getting import
ed.)
load.py
:
from pathlib import Path
print(f'In {Path(__file__).name}')
classLoad: pass
And finally here's a example of using it to only import
the Load
class:
ad_hoc.py
:
from my_package import import_classes
#from my_package import Load
import_classes('Load')
test = Load()
print(test)
Along with the output produced:
In __init__.py
In load.py
<my_package.load.Load object at 0x001FE4A8>
Solution 2:
Inside a folder oranges\
, this is our __init__.py
file:
__all__ = []
from pathlib import Path
from importlib import import_module
from sys import modules
package = modules[__name__]
initfile = Path(__file__)
for entry in initfile.parent.iterdir():
is_file = entry.is_file()
is_pyfile = entry.name.endswith('.py')
is_not_initpy = (entry != initfile)
if is_file and is_pyfile and is_not_initpy:
module_name = entry.name.removesuffix('.py')
module_path = __name__ + '.' + module_name
module = import_module(module_path)
setattr(package, module_name, module)
__all__.append(module_name)
When we do from oranges import *
, the code inside oranges\__init__.py
cycles through the *.py
files inside oranges\
(except __init__.py
), and for each .py
file does the following:
imports the
.py
file as a module into the variablemodule
using Python'simportlib.import_module
sets the
module
as a variable within the__init__.py
file (or, more correctly, within the oranges package) using Python'ssetattr
finally, appends the module to the
__all__
list
Post a Comment for "Package __init__.py Import All Subfiles, But Only Load One From Another Script?"