Search code examples
pythonpython-3.xpython-importlibpython-3.7imp

Python: Importing arbitrarily named source files using importlib


I use the imp module to import Python modules from source, given the absolute filename. I.e.

import imp
my_module = imp.load_source('my_module', '/paht/to/my_module')

Here, /paht/to/my_module is the full path to a file containing Python source code, even though it does not have a .py extension.

When doing import imp in Python 3.7, the following deprecation warning is shown:

DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses

I am thus in search for an importlib replacement of the imp.load_source function. From the docs, I have the following:

import importlib.util
spec = importlib.util.spec_from_file_location('my_module', '/paht/to/my_module')
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

This does not work when the filename has no extension, as in my case. I guess it fails because none of the implemented "finders" recognize the file as a Python source file. However, I do not really need all the complicated machinery provided by these finders, as I know for sure the absolute path to the file already. I simply want it imported.

A simple hack would be to just read in the source as text and execute it manually in its own namespace, something like

my_module = {} 
exec(open('/paht/to/my_module').read(), my_module)

(with this, names defined in my_module is available through my_module['name'] rather than my_module.name, but you get the idea). I would like to know the proper way of doing this, using importlib.


Solution

  • A solution to a similar question is posted here. Translated to my example:

    import importlib.machinery, importlib.util
    loader = importlib.machinery.SourceFileLoader('my_module', '/path/to/my_module')
    spec = importlib.util.spec_from_loader(loader.name, loader)
    my_module = importlib.util.module_from_spec(spec)
    loader.exec_module(my_module)