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

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


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


当前回答

我对@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。它添加了一些巧妙的技巧,例如在加载模块时将变量注入模块命名空间的能力。

其他回答

您可以使用

load_source(module_name, path_to_file)

方法。

一个使用importlib而不是imp包的简单解决方案(针对Python 2.7进行了测试,尽管它也适用于Python 3):

import importlib

dirname, basename = os.path.split(pyfilepath) # pyfilepath: '/my/path/mymodule.py'
sys.path.append(dirname) # only directories should be added to PYTHONPATH
module_name = os.path.splitext(basename)[0] # '/my/path/mymodule.py' --> 'mymodule'
module = importlib.import_module(module_name) # name space of defined module (otherwise we would literally look for "module_name")

现在您可以直接使用导入模块的名称空间,如下所示:

a = module.myvar
b = module.myfunc(a)

这种解决方案的优点是,为了在代码中使用它,我们甚至不需要知道要导入的模块的实际名称。这很有用,例如,如果模块的路径是可配置参数。

要从给定文件名导入模块,可以临时扩展路径,并在finally块引用中恢复系统路径:

filename = "directory/module.py"

directory, module_name = os.path.split(filename)
module_name = os.path.splitext(module_name)[0]

path = list(sys.path)
sys.path.insert(0, directory)
try:
    module = __import__(module_name)
finally:
    sys.path[:] = path # restore

下面是一些适用于所有Python版本的代码,从2.7-3.5到其他版本。

config_file = "/tmp/config.py"
with open(config_file) as f:
    code = compile(f.read(), config_file, 'exec')
    exec(code, globals(), locals())

我测试了它。它可能很难看,但到目前为止,它是唯一一个适用于所有版本的。

在Linux中,可以在Python脚本所在的目录中添加符号链接。

即。:

ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py

Python解释器将创建/aabsolute/path/to/script/module.pyc,如果您更改/aabsolute/path/to-module/module.py的内容,Python解释器将对其进行更新。

然后在文件mypythonscript.py中包含以下内容:

from module import *