Import arbitrary python source file. (Python 3.3+)
Found a solution from importlib
test code.
Using importlib.machinery.SourceFileLoader:
>>> import importlib.machinery>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')>>> mod = loader.load_module()>>> mod<module 'a_b' from '/tmp/a-b.txt'>
NOTE: only works in Python 3.3+.
UPDATE Loader.load_module
is deprecated since Python 3.4. Use Loader.exec_module
instead:
>>> import types>>> import importlib.machinery>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')>>> mod = types.ModuleType(loader.name)>>> loader.exec_module(mod)>>> mod<module 'a_b'>
>>> import importlib.machinery>>> import importlib.util>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')>>> spec = importlib.util.spec_from_loader(loader.name, loader)>>> mod = importlib.util.module_from_spec(spec)>>> loader.exec_module(mod)>>> mod<module 'a_b' from '/tmp/a-b.txt'>
Shorter version of @falsetru 's solution:
>>> import importlib.util>>> spec = importlib.util.spec_from_file_location('a_b', '/tmp/a-b.py')>>> mod = importlib.util.module_from_spec(spec)>>> spec.loader.exec_module(mod)>>> mod<module 'a_b' from '/tmp/a-b.txt'>
I tested it with Python 3.5 and 3.6.
According to the comments, it does not work with arbitrary file extensions.
Similar to @falsetru but for Python 3.5+ and accounting for what the importlib
doc states on using importlib.util.module_from_spec
over types.ModuleType
:
This function [
importlib.util.module_from_spec
] is preferred over usingtypes.ModuleType
to create a new module as spec is used to set as many import-controlled attributes on the module as possible.
We are able to import any file with importlib
alone by modifying the importlib.machinery.SOURCE_SUFFIXES
list.
import importlibimportlib.machinery.SOURCE_SUFFIXES.append('') # empty string to allow any filespec = importlib.util.spec_from_file_location(module_name, file_path)module = importlib.util.module_from_spec(spec)spec.loader.exec_module(module)# if desired: importlib.machinery.SOURCE_SUFFIXES.pop()