首页 > 解决方案 > 使用 import_module 从不同目录导入模块

问题描述

我在一个目录中有一个模块,需要由另一个目录中的脚本导入。但是,每当我尝试导入它时,我都会得到一个ModuleNotFoundError. 由于位于单独的 git repos 中,我必须将它们保存在单独的目录中。这是我的文件结构的示例:

└─ Documents
   ├─ ModuleRepo
   │  └─ myModule.py
   └─ ScriptRepo
      └─ myScript.py

该脚本myScript.py将模块名称作为命令行参数,然后使用以下命令导入它:

import importlib

def dynamic_import(module):
    return importlib.import_module(module)

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('modulename', help='Specify the module to import', type=str)
    args = parser.parse_args()
    
    mymodule = dynamic_import(args.modulename)

如果我导航到Documents/ModuleRepo并尝试运行python3 ../ScriptRepo/myScript.py myModule,则会出现错误ModuleNotFoundError: No module named 'myModule'。如果我myModule.py进入Documents/ScriptRepo,那么它会成功运行 - 所以我猜 python 只在正在运行的脚本的目录中寻找模块。这对我来说特别奇怪,因为这个确切的设置几个月前对我有用,但现在似乎没有。

我的最小目标是能够导航到Documents/ModuleRepo并运行python3 ../ScriptRepo/myScript.py myModule. 理想情况下(但不一定),我希望能够从任何地方运行,使用到和myScript.py的相对路径。myScript.pymyModule.py

我已经浏览了许多关于使用 动态导入的现有问题importlib,甚至在今年早些时候问过我自己的一个问题,但我仍然不知道如何解决将模块放在完全独立的目录中的问题。所以任何帮助将不胜感激。

标签: pythonpython-3.xmodulepython-importlib

解决方案


以下代码片段将允许您通过显式定义所需模块的路径来加载模块:

对于 Python 3.5+ 使用:

import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()

对于 Python 3.3 和 3.4,请使用:

from importlib.machinery import SourceFileLoader

foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()

(尽管这在 Python 3.4 中已被弃用。)

对于 Python 2 使用:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

推荐阅读