[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Import module from file path

On 05/12/2018 02:30, Oscar Benjamin wrote:
> Hi all,
> I'm looking to import a module given a string representing the path to
> the .py file defining the module. For example given this setup
> mkdir -p a/b/c
> touch a/__init__.py
> touch a/b/__init__.py
> touch a/b/c/__init__.py
> touch a/b/c/stuff.py
> I have a module a.b.c.stuff which is defined in the file
> '/home/oscar/work/project/a/b/c/stuff.py'. Given that a.b.c.stuff is
> importable and I have the (relative or absolute) path of stuff.py as a
> string I would like to import that module.
> I want this to work in 2.7 and 3.4+ and have come up with the
> following which works for valid inputs:

I might try something along the lines of: (untested)

if not filename.endswith('.py'):
    raise ValueError('not a .py file')
abs_filename = os.path.abspath(filename)
for path_root in sys.path:
    abs_root = os.path.abspath(path_root)
    if abs_filename.startswith(abs_root):
        rel_filename = os.path.relpath(abs_filename, abs_root)
	if '.' in rel_filename[:-3]:
            # '.' in directory names? can't be right!
	mod_name = rel_filename[:-3].replace(os.sep, '.')
            return importlib.import_module(mod_name)
        except ImportError:
    raise ValueError('not an importable module')

This should work with namespace packages.

> Also it seems as if there should be a simpler way to get from
> the path to the module name...

I doubt it. There's no reason for the import machinery to have such a
mechanism. Besides, not all modules have real file names (e.g. if they
live in zip files)

-- Thomas