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

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


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


当前回答

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

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

…但这应该能完成任务。

其他回答

这应该行得通

path = os.path.join('./path/to/folder/with/py/files', '*.py')
for infile in glob.glob(path):
    basename = os.path.basename(infile)
    basename_without_extension = basename[:-3]

    # http://docs.python.org/library/imp.html?highlight=imp#module-imp
    imp.load_source(basename_without_extension, infile)

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

凌乱,但它有效。

configfile = '~/config.py'

import os
import sys

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

import config

如果您的顶级模块不是一个文件,而是用__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属性出现”,如这里所讨论的。

创建Python模块test.py:

import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3

创建Python模块test_check.py:

from test import Client1
from test import Client2
from test import test3

我们可以从模块导入导入的模块。

我对@SebastianRittau的精彩回答(我认为Python>3.4)做了一个稍微修改的版本,它允许您使用spec_from_loader而不是spec_from_file_location加载具有任何扩展名的文件作为模块:

from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader 

spec = spec_from_loader("module.name", SourceFileLoader("module.name", "/path/to/file.py"))
mod = module_from_spec(spec)
spec.loader.exec_module(mod)

在显式SourceFileLoader中编码路径的优点是,机器不会试图从扩展名中找出文件的类型。这意味着您可以使用此方法加载类似.txt文件的文件,但如果不指定加载器,则无法使用spec_from_file_location加载,因为.txt不在importlib.machinery.SOURCE_SUFFIX中。

我已经在此基础上放置了一个实现,@SamGrondahl对我的实用程序库haggis进行了有用的修改。该函数名为hagis.load.load_module。它添加了一些巧妙的技巧,例如在加载模块时将变量注入模块命名空间的能力。