4

In Python, it is possible to dynamically import an entire module using importlib.import_module(name), which returns the specified package or module (e.g. pkg.mod). However, is there no analogous way to dynamically import a specific function/class/etc. from a given module in the same fashion as done using e.g. from foo import bar, where the symbol bar of the module foo is imported into the symbol table of the importing module?

For example, if I try to import a symbol directly using importlib.import_module(symbol_name), I just get an ImportError:

import importlib

# Importing an entire module works fine
imported_module = importlib.import_module("os.path")
# This doesn't work
imported_symbol = importlib.import_module("os.path.basename")

Executing the code above prints the following stack trace:

Traceback (most recent call last):
  File "/home/stackoverflow/dev/importtest.py", line 6, in <module>
    symbol = importlib.import_module("basename", "os.path.basename")
  File "/usr/lib/python3.5/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 956, in _find_and_load_unlocked
ImportError: No module named 'basename'
Community
  • 1
  • 1
errantlinguist
  • 3,658
  • 4
  • 18
  • 41

2 Answers2

4

You have to look up the symbol you need in the module object that is returned by import_module using getattr:

imported_module = importlib.import_module("os.path")
imported_symbol = getattr(imported_module, "basename")
fpbhb
  • 1,469
  • 10
  • 22
  • 1
    Is this preferred to `imported_symbol = imported_module.basename` ? The question does not ask about `basename` as a string but hardcoded in the script. – Mike C Jan 04 '23 at 23:25
  • 1
    No, it is not necessarily preferred. The dot notation and `getattr` do the same thing, except that `getattr` can have a default, which could be used for error checking etc. -- I'd normally do it with `getattr` because `"basename"` as a string mirrors using `"os.path"` as a string, and would not trigger static analyzers that check module signatures etc. – fpbhb Jan 05 '23 at 07:33
2

import_module method only accept module.

You could try something as below to access the module's method/attribute

imported_symbol = importlib.import_module("os.path").basename
Skycc
  • 3,496
  • 1
  • 12
  • 18