从字符串动态导入文件中的方法

Lak*_*sad 68 python import dynamic dynamic-import

我有一个字符串,说: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('.'))
Run Code Online (Sandbox Code Playgroud)

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

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

frm*_*frm 92

从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()
Run Code Online (Sandbox Code Playgroud)

  • `import_module`**+**`rsplit`**=**_The One True Way._ (3认同)
  • 值得注意的是,Python 文档建议使用 `importlib.import_module()` 而不是 `__import__()`:https://docs.python.org/2/library/functions.html#__import__ -- 对于 2.7+。 (2认同)

Sve*_*ach 28

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

def import_from(module, name):
    module = __import__(module, fromlist=[name])
    return getattr(module, name)
Run Code Online (Sandbox Code Playgroud)

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

import_from("abc.def.ghi.jkl.myfile", "mymethod")
Run Code Online (Sandbox Code Playgroud)

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

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

  • @twasbrillig:当我回答这个问题时,Python 2.5和2.6仍然被广泛使用.今天,最好使用`importlib`代替. (3认同)

gec*_*cco 20

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

__import__('abc.def.ghi.jkl.myfile.mymethod', fromlist=[''])
Run Code Online (Sandbox Code Playgroud)

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

importlib.import_module('abc.def.ghi.jkl.myfile.mymethod')
Run Code Online (Sandbox Code Playgroud)

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

Python <2.7:

mymethod = getattr(__import__("abc.def.ghi.jkl.myfile", fromlist=["mymethod"]))
Run Code Online (Sandbox Code Playgroud)

Python> = 2.7:

mymethod = getattr(importlib.import_module("abc.def.ghi.jkl.myfile"), "mymethod")
Run Code Online (Sandbox Code Playgroud)

  • 这些解决方案都不会起作用,因为第一个参数必须是`__import __()`和`importlib.import_module()`中的*模块名*. (6认同)

Cha*_*iam 8

目前还不清楚你要对你的本地命名空间做什么.我假设你只想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()
Run Code Online (Sandbox Code Playgroud)

虽然您只添加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()
Run Code Online (Sandbox Code Playgroud)

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


Ala*_*iel 8

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 
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答,只是一个小问题:我认为 `.strip()` 在您所说的情况下行为不正确。具体来说,如果文件以“py”开头,这些字符也将被删除。例如, `"pyfile.py".strip(".py")` 生成 `"file"`,在这种情况下最好生成 `"pyfile"`。不过, `name.replace(".py","")` 工作得很好。 (2认同)

Dan*_*man -1

使用importlib(仅限 2.7+)。

  • 不,“__future__”是针对语言功能的,而不是新的 stdlib 模块。 (5认同)