从绝对路径导入模块而不进行修改系统模块

2024-04-24 09:05:01 发布

您现在位置:Python中文网/ 问答频道 /正文

所以,我知道我可以加载一个python模块,给它一个指向该模块的文件路径

def import_module_from_fpath(module_fpath):
    from os.path import basename, splitext, isdir, join, exists, dirname, split
    import platform
    if isdir(module_fpath):
        module_fpath = join(module_fpath, '__init__.py')
    print('module_fpath = {!r}'.format(module_fpath))
    if not exists(module_fpath):
        raise ImportError('module_fpath={!r} does not exist'.format(
            module_fpath))
    python_version = platform.python_version()
    modname = splitext(basename(module_fpath))[0]
    if modname == '__init__':
        modname = split(dirname(module_fpath))[1]
    if python_version.startswith('2.7'):
        import imp
        module = imp.load_source(modname, module_fpath)
    elif python_version.startswith('3'):
        import importlib.machinery
        loader = importlib.machinery.SourceFileLoader(modname, module_fpath)
        module = loader.load_module()
        # module = loader.exec_module(modname)
    else:
        raise AssertionError('invalid python version={!r}'.format(
            python_version))
return module

但是,这似乎总是填充sys.modules中的一个条目?在

我有两个不同的模块在不同的路径上。从PYTHONPATH无法访问这两个模块。我希望能够在不同的函数中本地加载这些模块,并且不让它们相互干扰。这个问题的症结在于两个模块具有相同的名称(不同的版本)。因此,我不希望sys.modules在这两者之间缓存任何内容。在

我不确定在我加载模块之后仅仅从sys.modules中删除模块名是否安全。好像是我做的一个快速测试:

^{pr2}$

上面的脚本演示了当尝试加载两个同名的不同模块时会发生什么:它们相互覆盖/互补。但是,如果我做这个导入,然后直接删除所有导入的模块,它似乎做了“正确”的事情。在

我的问题是:

  1. 它真的做了“正确”的事吗?或者有没有我的脚本没有测试到的情况。

  2. 有没有一种方法可以在本地导入模块而不将其添加到sys.modules(也称为全局命名空间)中?(sys.modules是组成模块的全局命名空间的唯一事物吗?)

(我只在python3中测试了上述代码,不确定旧的imp模块是否与importlib相同)。在


Tags: 模块fromimport路径modulesformatifversion