Reputation: 68588
Say I have a directory foo
that contains some .py
files.
Each of these python files has a class Bar
defined.
Say there were three .py
files called baz.py
, qux.py
and quux.py
- then to get the bar classes I could write:
import foo.baz
import foo.qux
import foo.quux
bars = [
foo.baz.Bar,
foo.qux.Bar,
foo.quux.Bar,
]
However, rather than list out all the imports like this and all the Bar
names, I want to populate bars
programmatically.
That is, I want to write some code to populate bars
that doesn't change as .py
files are added or removed from the foo
directory.
One way to do this might be to use Path('foo').iterdir()
to list the .py
files, but then how do I do a programmatic import
of a string and name its Bar
class?
Or is there some totally different approach to achieve this?
bars = []
for py_file in the directory foo:
import foo.py_file ???
bars.append(foo.py_file.Bar) ???
Upvotes: 2
Views: 298
Reputation: 77337
You can use importlib
to import the modules dynamically. But you need to find them first. If you include foo.__init__.py
in the source, then then foo.__file__
will be that name. You can use that as the base of your glob, but you need to make sure you don't try to import __init__.py
itself. This technique is nice because you don't have to worry about another bit of source importing the same module name but getting a different module in memory.
from pathlib import Path
import importlib
import foo
def no_magic(paths):
for path in paths:
if not path.name.startswith("_"):
yield path
bars = []
for py in no_magic(Path(foo.__file__).resolve().parent.glob("*.py")):
mod = importlib.import_module(f"foo.{py.stem}", foo)
bars.append(mod.Bar)
print(bars)
Upvotes: 0
Reputation: 7538
Here is one approach using glob
module to match the pathnames of the modules we would like to import and importlib
's SourceFileLoader
to import.
from glob import glob
from importlib.machinery import SourceFileLoader
modules = glob('foo/*.py')
bars = list(map(lambda pathname: SourceFileLoader(".", pathname).load_module().Bar, modules))
Upvotes: 1