pythonclassmodulenotfounderrorpython-importlib

ModuleNotFoundError when using importlib inside of a class


I am attempting to import an object using importlib.import_module, but am getting a ModuleNotFoundError no matter what I try. I've read through as many related posts as I can find, but haven't been able to solve my problem.

Thank you in advance to anyone able to help!

My project folder is structured like this:

root/
   checks.py
   database.py
   main.py

checks.py is where I define the Check class. It contains the following code.

class Check():
    def __init__(self, action):
        self.action = action

    def speak(self):
        print(self.action)

class CheckOne(Check):
    def __init__(self):
        Check.__init__(self, "Performing the first check.")

    def apply_(self):
        self.speak()

database.py is where I define the Database class. It contains the following code.

class Database():
    def __init__(self):
        # The checks we want to perform
        self.check_names = ['CheckOne']
    
    def apply_checks(self):
        import importlib
        checks = [importlib.import_module(f'checks.{i}') for i in self.check_names]
        for c in checks:
            c().apply_()

main.py instantiates a Database object and calls apply_checks. It contains the following code:

from database import Database

db = Database()
db.apply_checks()

When I run main.py, I get the following error:

ModuleNotFoundError: No module named 'checks.CheckOne'; 'checks' is not a package

What I am intending is that Database.apply_checks imports the CheckOne class into a list, instantiates it, and then executes the CheckOne.apply_ method (printing "Performing the first check.").

I've tried placing import checks and from . import checks inside the Database class definition but to no avail. I've also tried adding an __init__.py file under root.

Thank you for reading, I appreciate the feedback!


Solution

  • Try this instead:

    import checks
    
    class Database():
        def __init__(self):
            # The checks we want to perform
            self.check_names = ['CheckOne']
        
        def apply_checks(self):
            check_classes = [getattr(checks, name) for name in self.check_names]
            for cls in check_classes:
                cls().apply_()