我有一个字符串,比如: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 版。
从 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()
您不需要导入各个模块。导入要从中导入名称的模块并提供 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
模块没有任何优势。
myClass = getattr(__import__("module.to.import", fromlist=["myClassName"]), "myClassName")
。谢谢您的帮助!
__import__
方法确实有效。但请尝试运行 help(__import__)
。它说“因为这个函数是供 Python 解释器使用的,而不是一般用途,最好使用 importlib.import_module()
以编程方式导入模块。”
importlib
。
对于 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")
__import__()
和 importlib.import_module()
中的 模块名称。
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
.strip()
在您所说的情况下行为不正确。具体来说,如果文件以“py”开头,这些字符也将被删除。例如,"pyfile.py".strip(".py")
生成 "file"
,在这种情况下最好生成 "pyfile"
。不过,name.replace(".py","")
工作得很好。
目前尚不清楚您要对本地命名空间做什么。我假设您只想将 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())
。为什么是一个复杂的讨论。
the_module
和 same_module
的第一个示例是错误的,会产生不同的结果。投反对票。
这个网站有一个很好的解决方案: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)
使用 importlib
(仅限 2.7+)。
from __future__
件事吗?
__future__
用于语言功能,而不是新的 stdlib 模块。
__import__
。它可以回溯到 2.5,并且在此之前没有关键字。
我倾向于这样做的方式(以及许多其他库,例如 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()
这个怎么样 :
def import_module(name):
mod = __import__(name)
for s in name.split('.')[1:]:
mod = getattr(mod, s)
return mod
importlib.import_module()
而不是__import__()
:docs.python.org/2/library/functions.html#__import__ - 用于 2.7+。import_module
+rsplit
= 一条真道。