ubelt.util_import module¶
Expose functions to simplify importing from module names and paths.
The ub.import_module_from_path()
function does its best to load a python file
into th current set of global modules.
The ub.import_module_from_name()
works similarly.
The ub.modname_to_modpath()
and ub.modname_to_modpath()
work
statically and convert between module names and file paths on disk.
The ub.split_modpath()
function separates modules into a root and base
path depending on where the first __init__.py
file is.
- ubelt.util_import.split_modpath(modpath, check=True)[source]¶
Splits the modpath into the dir that must be in PYTHONPATH for the module to be imported and the modulepath relative to this directory.
- Parameters
modpath (str) – module filepath
check (bool) – if False, does not raise an error if modpath is a directory and does not contain an
__init__.py
file.
- Returns
(directory, rel_modpath)
- Return type
tuple
- Raises
ValueError – if modpath does not exist or is not a package
Example
>>> from xdoctest import static_analysis >>> modpath = static_analysis.__file__.replace('.pyc', '.py') >>> modpath = abspath(modpath) >>> dpath, rel_modpath = split_modpath(modpath) >>> recon = join(dpath, rel_modpath) >>> assert recon == modpath >>> assert rel_modpath == join('xdoctest', 'static_analysis.py')
- ubelt.util_import.modname_to_modpath(modname, hide_init=True, hide_main=False, sys_path=None)[source]¶
Finds the path to a python module from its name.
Determines the path to a python module without directly import it
Converts the name of a module (__name__) to the path (__file__) where it is located without importing the module. Returns None if the module does not exist.
- Parameters
modname (str) – module filepath
hide_init (bool) – if False, __init__.py will be returned for packages
hide_main (bool) – if False, and hide_init is True, __main__.py will be returned for packages, if it exists.
sys_path (list, default=None) – if specified overrides
sys.path
- Returns
modpath - path to the module, or None if it doesn’t exist
- Return type
str
Example
>>> modname = 'xdoctest.__main__' >>> modpath = modname_to_modpath(modname, hide_main=False) >>> assert modpath.endswith('__main__.py') >>> modname = 'xdoctest' >>> modpath = modname_to_modpath(modname, hide_init=False) >>> assert modpath.endswith('__init__.py') >>> # xdoctest: +REQUIRES(CPython) >>> modpath = basename(modname_to_modpath('_ctypes')) >>> assert 'ctypes' in modpath
- ubelt.util_import.modpath_to_modname(modpath, hide_init=True, hide_main=False, check=True, relativeto=None)[source]¶
Determines importable name from file path
Converts the path to a module (__file__) to the importable python name (__name__) without importing the module.
The filename is converted to a module name, and parent directories are recursively included until a directory without an __init__.py file is encountered.
- Parameters
modpath (str) – module filepath
hide_init (bool, default=True) – removes the __init__ suffix
hide_main (bool, default=False) – removes the __main__ suffix
check (bool, default=True) – if False, does not raise an error if modpath is a dir and does not contain an __init__ file.
relativeto (str, default=None) – if specified, all checks are ignored and this is considered the path to the root module.
Todo
- [ ] Does this need modification to support PEP 420?
- Returns
modname
- Return type
str
- Raises
ValueError – if check is True and the path does not exist
Example
>>> from xdoctest import static_analysis >>> modpath = static_analysis.__file__.replace('.pyc', '.py') >>> modpath = modpath.replace('.pyc', '.py') >>> modname = modpath_to_modname(modpath) >>> assert modname == 'xdoctest.static_analysis'
Example
>>> import xdoctest >>> assert modpath_to_modname(xdoctest.__file__.replace('.pyc', '.py')) == 'xdoctest' >>> assert modpath_to_modname(dirname(xdoctest.__file__.replace('.pyc', '.py'))) == 'xdoctest'
Example
>>> # xdoctest: +REQUIRES(CPython) >>> modpath = modname_to_modpath('_ctypes') >>> modname = modpath_to_modname(modpath) >>> assert modname == '_ctypes'
Example
>>> modpath = '/foo/libfoobar.linux-x86_64-3.6.so' >>> modname = modpath_to_modname(modpath, check=False) >>> assert modname == 'libfoobar'
- ubelt.util_import.import_module_from_name(modname)[source]¶
Imports a module from its string name (__name__)
- Parameters
modname (str) – module name
- Returns
module
- Return type
module
Example
>>> # test with modules that wont be imported in normal circumstances >>> # todo write a test where we gaurentee this >>> modname_list = [ >>> 'pickletools', >>> 'lib2to3.fixes.fix_apply', >>> ] >>> #assert not any(m in sys.modules for m in modname_list) >>> modules = [import_module_from_name(modname) for modname in modname_list] >>> assert [m.__name__ for m in modules] == modname_list >>> assert all(m in sys.modules for m in modname_list)
- ubelt.util_import.import_module_from_path(modpath, index=- 1)[source]¶
Imports a module via its path
- Parameters
modpath (PathLike) – path to the module on disk or within a zipfile.
index (int) – location at which we modify PYTHONPATH if necessary. If your module name does not conflict, the safest value is -1, However, if there is a conflict, then use an index of 0. The default may change to 0 in the future.
- Returns
the imported module
- Return type
module
References
https://stackoverflow.com/questions/67631/import-module-given-path
Notes
If the module is part of a package, the package will be imported first. These modules may cause problems when reloading via IPython magic
This can import a module from within a zipfile. To do this modpath should specify the path to the zipfile and the path to the module within that zipfile separated by a colon or pathsep. E.g. “/path/to/archive.zip:mymodule.pl”
Warning
It is best to use this with paths that will not conflict with previously existing modules.
If the modpath conflicts with a previously existing module name. And the target module does imports of its own relative to this conflicting path. In this case, the module that was loaded first will win.
For example if you try to import ‘/foo/bar/pkg/mod.py’ from the folder structure:
If there exists another module named
pkg
already in sys.modules and mod.py does something likefrom . import helper
, Python will assume helper belongs to thepkg
module already in sys.modules. This can cause a NameError or worse — a incorrect helper module.Example
>>> import xdoctest >>> modpath = xdoctest.__file__ >>> module = import_module_from_path(modpath) >>> assert module is xdoctest
Example
>>> # Test importing a module from within a zipfile >>> import zipfile >>> from xdoctest import utils >>> from os.path import join, expanduser >>> dpath = expanduser('~/.cache/xdoctest') >>> dpath = utils.ensuredir(dpath) >>> #dpath = utils.TempDir().ensure() >>> # Write to an external module named bar >>> external_modpath = join(dpath, 'bar.py') >>> # For pypy support we have to write this using with >>> with open(external_modpath, 'w') as file: >>> file.write('testvar = 1') >>> internal = 'folder/bar.py' >>> # Move the external bar module into a zipfile >>> zippath = join(dpath, 'myzip.zip') >>> with zipfile.ZipFile(zippath, 'w') as myzip: >>> myzip.write(external_modpath, internal) >>> # Import the bar module from within the zipfile >>> modpath = zippath + ':' + internal >>> modpath = zippath + os.path.sep + internal >>> module = import_module_from_path(modpath) >>> assert module.__name__ == os.path.normpath('folder/bar') >>> assert module.testvar == 1
Example
>>> import pytest >>> with pytest.raises(IOError): >>> import_module_from_path('does-not-exist') >>> with pytest.raises(IOError): >>> import_module_from_path('does-not-exist.zip/')