Import arbitrary python source file. (Python 3.3+) Import arbitrary python source file. (Python 3.3+) python python

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 using types.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()