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

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


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


当前回答

我发现这是一个简单的答案:

module = dict()

code = """
import json

def testhi() :
    return json.dumps({"key" : "value"}, indent = 4 )
"""

exec(code, module)
x = module['testhi']()
print(x)

其他回答

我认为,最好的方法是从官方文件(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()

我并不是说它更好,但为了完整起见,我想建议在Python2和Python3中使用exec函数。

exec允许您在全局作用域或作为字典提供的内部作用域中执行任意代码。

例如,如果您有一个模块存储在带有函数foo()的“/path/to/module”中,您可以通过执行以下操作来运行它:

module = dict()
with open("/path/to/module") as f:
    exec(f.read(), module)
module['foo']()

这使得动态加载代码更加明确,并赋予您一些额外的功能,例如提供自定义内置功能的能力。

如果通过属性而不是键访问对你来说很重要,你可以为全局变量设计一个自定义dict类,提供这样的访问,例如:

class MyModuleClass(dict):
    def __getattr__(self, name):
        return self.__getitem__(name)

特殊的是使用Exec()导入具有绝对路径的模块:(exec采用代码字符串或代码对象。而eval采用表达式。)

PYMODULE = 'C:\maXbox\mX47464\maxbox4\examples\histogram15.py';
Execstring(LoadStringJ(PYMODULE));

然后使用eval()获取值或对象:

println('get module data: '+evalStr('pyplot.hist(x)'));

使用exec加载模块就像使用通配符命名空间导入:

Execstring('sys.path.append(r'+'"'+PYMODULEPATH+'")');
Execstring('from histogram import *'); 

对于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.

为了补充塞巴斯蒂安·里托的回答:至少对于CPython,有pydoc,虽然没有正式声明,但导入文件就是它的作用:

from pydoc import importfile
module = importfile('/path/to/module.py')

PS。为了完整起见,在撰写本文时,这里提到了当前的实现:pydoc.py,我很高兴地说,在xkcd 1987的脉络中,它没有使用第21436期中提到的任何一个实现,至少没有逐字逐句地使用。