如何加载给定完整路径的Python模块?
请注意,文件可以位于文件系统中用户具有访问权限的任何位置。
另请参阅:如何导入以字符串形式命名的模块?
如何加载给定完整路径的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。它添加了一些巧妙的技巧,例如在加载模块时将变量注入模块命名空间的能力。
其他回答
这里有一种加载文件的方法,类似于C等。
from importlib.machinery import SourceFileLoader
import os
def LOAD(MODULE_PATH):
if (MODULE_PATH[0] == "/"):
FULL_PATH = MODULE_PATH;
else:
DIR_PATH = os.path.dirname (os.path.realpath (__file__))
FULL_PATH = os.path.normpath (DIR_PATH + "/" + MODULE_PATH)
return SourceFileLoader (FULL_PATH, FULL_PATH).load_module ()
在以下情况下实施:
Y = LOAD("../Z.py")
A = LOAD("./A.py")
D = LOAD("./C/D.py")
A_ = LOAD("/IMPORTS/A.py")
Y.DEF();
A.DEF();
D.DEF();
A_.DEF();
其中每个文件如下所示:
def DEF():
print("A");
这个答案是对Sebastian Rittau对评论的回答的补充:“但是如果你没有模块名怎么办?”这是一种快速而肮脏的方法,可以将可能的Python模块名指定为文件名——它只是沿着树向上移动,直到找到一个没有__init__.py文件的目录,然后将其转换回文件名。对于Python 3.4+(使用pathlib),这是有意义的,因为Python 2可以使用“imp”或其他方式进行相对导入:
import pathlib
def likely_python_module(filename):
'''
Given a filename or Path, return the "likely" python module name. That is, iterate
the parent directories until it doesn't contain an __init__.py file.
:rtype: str
'''
p = pathlib.Path(filename).resolve()
paths = []
if p.name != '__init__.py':
paths.append(p.stem)
while True:
p = p.parent
if not p:
break
if not p.is_dir():
break
inits = [f for f in p.iterdir() if f.name == '__init__.py']
if not inits:
break
paths.append(p.stem)
return '.'.join(reversed(paths))
当然有改进的可能性,可选的__init__.py文件可能需要进行其他更改,但如果您通常有__init__.pry,这就有了窍门。
向sys.path添加路径(与使用imp相比)的优点是,当从单个包导入多个模块时,可以简化操作。例如:
import sys
# the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py
sys.path.append('/foo/bar/mock-0.3.1')
from testcase import TestCase
from testutils import RunTests
from mock import Mock, sentinel, patch
要导入模块,需要将其目录临时或永久添加到环境变量中。
暂时
import sys
sys.path.append("/path/to/my/modules/")
import my_module
永久地
在Linux中将以下行添加到.bashrc(或替代)文件中以及终端中的exccute source~/.bashrc(或替代):
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
信贷/来源:saarrrr,另一个Stack Exchange问题
对于Python 3.5+,使用(docs):
import importlib.util
import sys
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
sys.modules["module.name"] = foo
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()
编译后的Python文件和DLL有等效的方便函数。
另请参见http://bugs.python.org/issue21436.