1

I want to import a module programmatically given a string representation of the module. I can do this with:

>>> import importlib
>>> m = importlib.import_module('some.path.module')
>>> m.greet('bob')
Hello, bob

However, the location I have is actually a variable defined as a path, either relative or absolute, along with a second variable for the filename. So it would be in this case:

path = 'some/path'
file = 'module.py'

I cannot use os.path.join(path, file), as this results in some/path/module.py, which is not valid input to importlib.import_module.

I could use os.path.join(path, file).replace('/', '.').replace('.py', ''), which would give 'some.path.module', but this gives problems when using absolute paths that begin with a slash for example, like /home/me/code/importing/some/path/module.py -> .home.me.code.importing.some.path.module - we would need to use os.path.join(path, file).replace('/', '.').replace('.py', '').lstrip('.'). Not only is that a bit ugly, I'm not actually sure if it is appropriate to use importlib to import in that way anyway - the dots in home.me.code.importing.some.path.module suggest that any one of those levels could be a subpackage with valid python code, as this is how it would appear if importing directly. For example, it implies that we might import it like:

from home.me.code.importing.some.path import module

suggesting that this is just a nested package within the home package which is obviously not correct.

Is there a robust way to do this? Ideally I want to do this without installing other dependencies. Also, I would like to understand if there would be any unexpected issues about importing with a path in such a way.

fffrost
  • 1,659
  • 1
  • 21
  • 36
  • Does this answer your question? [How can I import a module dynamically given the full path?](https://stackoverflow.com/questions/67631/how-can-i-import-a-module-dynamically-given-the-full-path) – Alireza Roshanzamir Jul 09 '23 at 22:16

1 Answers1

1

You can use importlib.util.spec_from_file_location for this

import os
import importlib.util

path = '/my/path'
file = 'module.py'
module_name = 'my_module' 
module_path = os.path.join(path, file)

spec = importlib.util.spec_from_file_location(module_name, module_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

print(module.foo())
Norhther
  • 545
  • 3
  • 15
  • 35