pje*_*esi 147 python reflection python-import
给定一个Python类的字符串,例如my_package.my_module.MyClass,加载它的最佳方法是什么?
换句话说,我正在寻找Class.forName()Java中的等效函数,Python中的函数.它需要在Google App Engine上运行.
最好这是一个函数,它接受类的FQN作为字符串,并返回对类的引用:
my_class = load_class('my_package.my_module.MyClass')
my_instance = my_class()
Run Code Online (Sandbox Code Playgroud)
Jas*_*ker 181
从python文档中,这是你想要的功能:
def my_import(name):
components = name.split('.')
mod = __import__(components[0])
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
Run Code Online (Sandbox Code Playgroud)
简单__import__不起作用的原因是因为任何超出包字符串中第一个点的内容都是您要导入的模块的属性.因此,这样的事情是行不通的:
__import__('foo.bar.baz.qux')
Run Code Online (Sandbox Code Playgroud)
你必须像这样调用上面的函数:
my_import('foo.bar.baz.qux')
Run Code Online (Sandbox Code Playgroud)
或者就你的例子而言:
klass = my_import('my_package.my_module.my_class')
some_object = klass()
Run Code Online (Sandbox Code Playgroud)
编辑:我有点偏僻.你基本上想要做的是:
from my_package.my_module import my_class
Run Code Online (Sandbox Code Playgroud)
仅当您有一个空的 fromlist时,才需要上述功能.因此,适当的调用将是这样的:
mod = __import__('my_package.my_module', fromlist=['my_class'])
klass = getattr(mod, 'my_class')
Run Code Online (Sandbox Code Playgroud)
cha*_*rik 109
如果你不想自己动手,那么pydoc模块中有一个功能就是这样:
from pydoc import locate
my_class = locate('my_package.my_module.MyClass')
Run Code Online (Sandbox Code Playgroud)
这种方法优于此处列出的其他方法的优点是可以在提供的虚线路径上locate找到任何 python对象,而不仅仅是模块中直接的对象.例如my_package.my_module.MyClass.attr.
如果你很好奇他们的食谱是什么,这里的功能是:
def locate(path, forceload=0):
"""Locate an object by name or dotted path, importing as necessary."""
parts = [part for part in split(path, '.') if part]
module, n = None, 0
while n < len(parts):
nextmodule = safeimport(join(parts[:n+1], '.'), forceload)
if nextmodule: module, n = nextmodule, n + 1
else: break
if module:
object = module
else:
object = __builtin__
for part in parts[n:]:
try:
object = getattr(object, part)
except AttributeError:
return None
return object
Run Code Online (Sandbox Code Playgroud)
它依赖于pydoc.safeimport功能.以下是有关的文档:
"""Import a module; handle errors; return None if the module isn't found.
If the module *is* found but an exception occurs, it's wrapped in an
ErrorDuringImport exception and reraised. Unlike __import__, if a
package path is specified, the module at the end of the path is returned,
not the package at the beginning. If the optional 'forceload' argument
is 1, we reload the module from disk (unless it's a dynamic extension)."""
Run Code Online (Sandbox Code Playgroud)
Ada*_*nce 84
import importlib
module = importlib.import_module('my_package.my_module')
my_class = getattr(module, 'MyClass')
my_instance = my_class()
Run Code Online (Sandbox Code Playgroud)
Sta*_*tan 29
def import_class(cl):
d = cl.rfind(".")
classname = cl[d+1:len(cl)]
m = __import__(cl[0:d], globals(), locals(), [classname])
return getattr(m, classname)
Run Code Online (Sandbox Code Playgroud)
Jav*_*zzi 11
如果您使用的是Django,则可以使用它。是的,我知道OP并没有要求使用django,但是我遇到了这个问题,寻找Django解决方案,没有找到一个解决方案,并将其放在这里供下一个寻找它的下一个男孩/女孩使用。
# It's available for v1.7+
# https://github.com/django/django/blob/stable/1.7.x/django/utils/module_loading.py
from django.utils.module_loading import import_string
Klass = import_string('path.to.module.Klass')
func = import_string('path.to.module.func')
var = import_string('path.to.module.var')
Run Code Online (Sandbox Code Playgroud)
请记住,如果您要导入没有.,re或的东西,请argparse使用:
re = __import__('re')
Run Code Online (Sandbox Code Playgroud)
这里分享一些我就发现__import__并importlib试图解决这个问题。
我正在使用 Python 3.7.3。
当我尝试d在模块中上课时a.b.c,
mod = __import__('a.b.c')
Run Code Online (Sandbox Code Playgroud)
该mod变量是指顶部的命名空间a。
所以为了去上课d,我需要
mod = getattr(mod, 'b') #mod is now module b
mod = getattr(mod, 'c') #mod is now module c
mod = getattr(mod, 'd') #mod is now class d
Run Code Online (Sandbox Code Playgroud)
如果我们尝试做
mod = __import__('a.b.c')
d = getattr(mod, 'd')
Run Code Online (Sandbox Code Playgroud)
我们实际上是在寻找a.d.
使用时importlib,我想图书馆已经getattr为我们完成了递归。所以,当我们使用 时importlib.import_module,我们实际上得到了最深模块的句柄。
mod = importlib.import_module('a.b.c') #mod is module c
d = getattr(mod, 'd') #this is a.b.c.d
Run Code Online (Sandbox Code Playgroud)