105

我有一个字符串,说:abc.def.ghi.jkl.myfile.mymethod。如何动态导入mymethod

这是我的做法:

def get_method_from_file(full_path):
    if len(full_path) == 1:
        return map(__import__,[full_path[0]])[0]
    return getattr(get_method_from_file(full_path[:-1]),full_path[-1])


if __name__=='__main__':
    print get_method_from_file('abc.def.ghi.jkl.myfile.mymethod'.split('.'))

我想知道是否需要导入单个模块。

编辑:我使用的是 Python 2.6.5 版。

4

9 回答 9

121

从 Python 2.7 开始,您可以使用importlib.import_module()函数。您可以使用以下代码导入模块并访问其中定义的对象:

from importlib import import_module

p, m = name.rsplit('.', 1)

mod = import_module(p)
met = getattr(mod, m)

met()
于 2012-01-09T14:51:01.100 回答
35

您不需要导入各个模块。导入要从中导入名称的模块并提供fromlist参数就足够了:

def import_from(module, name):
    module = __import__(module, fromlist=[name])
    return getattr(module, name)

对于您的示例abc.def.ghi.jkl.myfile.mymethod,将此函数称为

import_from("abc.def.ghi.jkl.myfile", "mymethod")

(请注意,模块级函数在 Python 中称为函数,而不是方法。)

importlib对于这样一个简单的任务,使用该模块没有任何优势。

于 2012-01-09T14:39:26.213 回答
30

对于 Python < 2.7,可以使用内置方法__ import__ :

__import__('abc.def.ghi.jkl.myfile.mymethod', fromlist=[''])

对于 Python >= 2.7 或 3.1,添加了方便的方法importlib.import_module。只需像这样导入您的模块:

importlib.import_module('abc.def.ghi.jkl.myfile.mymethod')

更新:根据评论更新版本(我必须承认我直到最后都没有阅读要导入的字符串,我错过了应该导入模块的方法而不是模块本身的事实)

蟒蛇 < 2.7 :

mymethod = getattr(__import__("abc.def.ghi.jkl.myfile", fromlist=["mymethod"]))

蟒蛇> = 2.7:

mymethod = getattr(importlib.import_module("abc.def.ghi.jkl.myfile"), "mymethod")
于 2012-01-09T14:37:25.690 回答
12

目前尚不清楚您要对本地命名空间做什么。我假设你想my_method作为一个本地人,打字output = my_method()

# This is equivalent to "from a.b.myfile import my_method"
the_module = importlib.import_module("a.b.myfile")
same_module = __import__("a.b.myfile")
# import_module() and __input__() only return modules
my_method = getattr(the_module, "my_method")

# or, more concisely,
my_method = getattr(__import__("a.b.myfile"), "my_method")
output = my_method()

虽然您只添加my_method到本地命名空间,但您确实加载了模块链。sys.modules您可以通过查看导入前后的键来查看更改。我希望这比您的其他答案更清晰,更准确。

为了完整起见,这就是添加整个链的方式。

# This is equivalent to "import a.b.myfile"
a = __import__("a.b.myfile")
also_a = importlib.import_module("a.b.myfile")
output = a.b.myfile.my_method()

# This is equivalent to "from a.b import myfile"
myfile = __import__("a.b.myfile", fromlist="a.b")
also_myfile = importlib.import_module("a.b.myfile", "a.b")
output = myfile.my_method()

最后,如果您正在使用__import__()并在程序启动后修改了您的搜索路径,您可能需要使用__import__(normal args, globals=globals(), locals=locals()). 为什么是一个复杂的讨论。

于 2013-06-07T04:50:50.537 回答
11
from importlib import import_module

name = "file.py".strip('.py')
# if Path like : "path/python/file.py" 
# use name.replaces("/",".")

imp = import_module(name)

# get Class From File.py
model = getattr(imp, "classNameImportFromFile")

NClass = model() # Class From file 
于 2018-01-15T03:26:07.923 回答
2

这个网站有一个很好的解决方案:load_class。我这样使用它:

foo = load_class(package.subpackage.FooClass)()
type(foo) # returns FooClass

根据要求,这是来自网络链接的代码:

import importlib

def load_class(full_class_string):
    """
    dynamically load a class from a string
    """

    class_data = full_class_string.split(".")
    module_path = ".".join(class_data[:-1])
    class_str = class_data[-1]

    module = importlib.import_module(module_path)
    # Finally, we retrieve the Class
    return getattr(module, class_str)
于 2017-11-10T16:30:04.203 回答
0

使用importlib(仅限 2.7+)。

于 2012-01-09T14:35:34.340 回答
-1

我倾向于这样做的方式(以及许多其他库,例如 pylons 和 paste,如果我没记错的话)是通过在它们之间使用“:”将模块名称与函数/属性名称分开. 请参见以下示例:

'abc.def.ghi.jkl.myfile:mymethod'

这使得import_from(path)下面的函数更容易使用。

def import_from(path):
    """
    Import an attribute, function or class from a module.
    :attr path: A path descriptor in the form of 'pkg.module.submodule:attribute'
    :type path: str
    """
    path_parts = path.split(':')
    if len(path_parts) < 2:
        raise ImportError("path must be in the form of pkg.module.submodule:attribute")
    module = __import__(path_parts[0], fromlist=path_parts[1])
    return getattr(module, path_parts[1])


if __name__=='__main__':
    func = import_from('a.b.c.d.myfile:mymethod')
    func()
于 2012-01-09T15:13:53.907 回答
-1

这个怎么样 :

def import_module(name):

    mod = __import__(name)
    for s in name.split('.')[1:]:
        mod = getattr(mod, s)
    return mod
于 2019-02-01T01:23:24.717 回答