如何加载给定完整路径的Python模块?

请注意,文件可以位于文件系统中用户具有访问权限的任何位置。


另请参阅:如何导入以字符串形式命名的模块?


当前回答

您也可以执行类似的操作,将配置文件所在的目录添加到Python加载路径中,然后进行正常导入,假设您事先知道文件的名称,在本例中为“config”。

凌乱,但它有效。

configfile = '~/config.py'

import os
import sys

sys.path.append(os.path.dirname(os.path.expanduser(configfile)))

import config

其他回答

有一个包专门针对这一点:

from thesmuggler import smuggle

# À la `import weapons`
weapons = smuggle('weapons.py')

# À la `from contraband import drugs, alcohol`
drugs, alcohol = smuggle('drugs', 'alcohol', source='contraband.py')

# À la `from contraband import drugs as dope, alcohol as booze`
dope, booze = smuggle('drugs', 'alcohol', source='contraband.py')

它在Python版本(Jython和PyPy也是)中进行了测试,但根据项目的大小,它可能会被过度使用。

我认为,最好的方法是从官方文件(29.1。imp-访问导入内部构件):

import imp
import sys

def __import__(name, globals=None, locals=None, fromlist=None):
    # Fast path: see if the module has already been imported.
    try:
        return sys.modules[name]
    except KeyError:
        pass

    # If any of the following calls raises an exception,
    # there's a problem we can't handle -- let the caller handle it.

    fp, pathname, description = imp.find_module(name)

    try:
        return imp.load_module(name, fp, pathname, description)
    finally:
        # Since we may exit via an exception, close fp explicitly.
        if fp:
            fp.close()

如果我们在同一个项目中有脚本,但在不同的目录方式中,我们可以通过以下方法解决这个问题。

在这种情况下,utils.py位于src/main/util中/

import sys
sys.path.append('./')

import src.main.util.utils
#or
from src.main.util.utils import json_converter # json_converter is example method

我相信您可以使用imp.find_module()和imp.load_module)来加载指定的模块。您需要将模块名称从路径中分离出来,即,如果要加载/home/mypath/mymodule.py,则需要执行以下操作:

imp.find_module('mymodule', '/home/mypath/')

…但这应该能完成任务。

如果您的顶级模块不是一个文件,而是用__init__.py打包成一个目录,那么接受的解决方案几乎可以工作,但不完全可以。在Python 3.5+中,需要以下代码(请注意添加的以“sys.modules”开头的行):

MODULE_PATH = "/path/to/your/module/__init__.py"
MODULE_NAME = "mymodule"
import importlib
import sys
spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module 
spec.loader.exec_module(module)

如果没有这一行,当exec_module被执行时,它会尝试将顶级__init__.py中的相对导入绑定到顶级模块名称——在本例中是“mymodule”。但“mymodule”尚未加载,因此您将收到错误“SystemError:父模块‘mymodule’未加载,无法执行相对导入”。因此,您需要在加载名称之前绑定它。原因是相对导入系统的基本不变:“不变保持是,如果您有sys.modules['spam']和sys.modules['spam.foo'](正如您在上述导入之后所做的那样),后者必须作为前者的foo属性出现”,如这里所讨论的。