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

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


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


当前回答

要导入模块,需要将其目录临时或永久添加到环境变量中。

暂时

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问题

其他回答

我并不是说它更好,但为了完整起见,我想建议在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)

在运行时导入包模块(Python配方)

http://code.activestate.com/recipes/223972/

###################
##                #
## classloader.py #
##                #
###################

import sys, types

def _get_mod(modulePath):
    try:
        aMod = sys.modules[modulePath]
        if not isinstance(aMod, types.ModuleType):
            raise KeyError
    except KeyError:
        # The last [''] is very important!
        aMod = __import__(modulePath, globals(), locals(), [''])
        sys.modules[modulePath] = aMod
    return aMod

def _get_func(fullFuncName):
    """Retrieve a function object from a full dotted-package name."""

    # Parse out the path, module, and function
    lastDot = fullFuncName.rfind(u".")
    funcName = fullFuncName[lastDot + 1:]
    modPath = fullFuncName[:lastDot]

    aMod = _get_mod(modPath)
    aFunc = getattr(aMod, funcName)

    # Assert that the function is a *callable* attribute.
    assert callable(aFunc), u"%s is not callable." % fullFuncName

    # Return a reference to the function itself,
    # not the results of the function.
    return aFunc

def _get_class(fullClassName, parentClass=None):
    """Load a module and retrieve a class (NOT an instance).

    If the parentClass is supplied, className must be of parentClass
    or a subclass of parentClass (or None is returned).
    """
    aClass = _get_func(fullClassName)

    # Assert that the class is a subclass of parentClass.
    if parentClass is not None:
        if not issubclass(aClass, parentClass):
            raise TypeError(u"%s is not a subclass of %s" %
                            (fullClassName, parentClass))

    # Return a reference to the class itself, not an instantiated object.
    return aClass


######################
##       Usage      ##
######################

class StorageManager: pass
class StorageManagerMySQL(StorageManager): pass

def storage_object(aFullClassName, allOptions={}):
    aStoreClass = _get_class(aFullClassName, StorageManager)
    return aStoreClass(allOptions)

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

听起来您不想专门导入配置文件(这会带来很多副作用和额外的复杂性)。您只需要运行它,并能够访问生成的命名空间。标准库以runpy.run_path的形式专门提供了一个API:

from runpy import run_path
settings = run_path("/path/to/file.py")

该接口在Python 2.7和Python 3.2+中可用。

您可以使用

load_source(module_name, path_to_file)

方法。