Python's import statement needs a "module name", not a file path to work. The way to import using a variable is to use the importlib.import_module
built-in function.
You have, of course, to use your filesystem "path" directory names to package names, and the top most of which must be "visible" in the PythonPath. The [:-3]
part is just there to strip the .py
part, but you can just use the modulename without the ".py" to startwith.
from importlib import import_module
module = importmodule('.'.join([path1, path2, filename[:-3]])
for attr in dir(module):
globals()[attr] = getattr(module, attr)
However, as you see, you will populate your namespace with names you don't know which they are, and thus, you can't have program code using those names - what makes it kind of pointless. It may be more useful to simply create a new dictionary with the attributes of your imported module:
namespace = {}
for attr in dir(module):
namespace[attr] = getattr(module, attr)
so you can introspect what was imported and call/use those values.
Now, if your "path1", and "path2" are not a package, and you really want to just import module from an arbitrary location, what is needed is to have the location inserted in the Pythonpath bedore calling import_module
. The Pythonpath, however, is a simple list located at sys.path
- just insert the full-folder path there (and pop it later if you want):
def import_path(path1, path2, module_name, namespace=None):
import sys
from importlib import import_module
from pathlib import Path # new code should use this instead of "os.path" stuff
path = Path(path1).joinpath(path2)
name = module_name[-3:] if module_name.endswith(".py") else module_name
try:
sys.path.insert(0, str(path))
module = import_module(name)
finally:
sys.path.remove(str(path))
if namespace is None:
namespace = sys._getframe().f_back.f_globals()
for name in dir(module):
namespace[name] = getattr(module, name)
(One can also use directly the __import__
function without needing to to use importlib.import_module
, but its use is not advised in the documentation. Among other things when using the single argument form __import__("path1.path2.module")
will return path1
not module
.)