46

I have class called 'my_class' placed in 'my_module'. And I need to import this class. I tried to do it like this:

import importlib
result = importlib.import_module('my_module.my_class')

but it says:

ImportError: No module named 'my_module.my_class'; 'my_module' is not a package

So. As I can see it works only for modules, but can't handle classes. How can I import a class from a module?

GhostKU
  • 1,898
  • 6
  • 23
  • 32

2 Answers2

75

It is expecting my_module to be a package containing a module named 'my_class'. If you need to import a class, or an attribute in general, dynamically, just use getattr after you import the module:

cls = getattr(import_module('my_module'), 'my_class')

Also, yes, it does only work with modules. Remember importlib.import_module is a wrapper of the internal importlib.__import__ function. It doesn't offer the same amount of functionality as the full import statement which, coupled with from, performs an attribute look-up on the imported module.

ᴍᴇʜᴏᴠ
  • 4,804
  • 4
  • 44
  • 57
Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
  • This is great! Another useful tip to use rpartition on string ``` class_path = 'my_module.my_class' module_name, _, class_name = class_path.rpartition('.') klass = getattr(import_module(module_name), class_name) ``` – The Doctor Nov 11 '20 at 17:36
7
import importlib
import logging

logger = logging.getLogger(__name__)


def factory(module_class_string, super_cls: type = None, **kwargs):
    """
    :param module_class_string: full name of the class to create an object of
    :param super_cls: expected super class for validity, None if bypass
    :param kwargs: parameters to pass
    :return:
    """
    module_name, class_name = module_class_string.rsplit(".", 1)
    module = importlib.import_module(module_name)
    assert hasattr(module, class_name), "class {} is not in {}".format(class_name, module_name)
    logger.debug('reading class {} from module {}'.format(class_name, module_name))
    cls = getattr(module, class_name)
    if super_cls is not None:
        assert issubclass(cls, super_cls), "class {} should inherit from {}".format(class_name, super_cls.__name__)
    logger.debug('initialising {} with params {}'.format(class_name, kwargs))
    obj = cls(**kwargs)
    return obj
Hanan Shteingart
  • 8,480
  • 10
  • 53
  • 66
  • 11
    Avoid code-only answers. Add some text to describe what is going on for people who might not understand it. Also, using `hasattr` with an `assert` is counter-intuitive; let `getattr` throw its exception instead. – Dimitris Fasarakis Hilliard Dec 07 '18 at 09:09