在动态导入模块中,从类的字符串名动态实例化Python

时间:2022-10-07 23:14:49

In python, I have to instantiate certain class, knowing its name in a string, but this class 'lives' in a dynamically imported module. An example follows:

在python中,我必须实例化某个类,知道它的名称在字符串中,但是这个类“存在”在动态导入的模块中。一个例子:

loader-class script:

loader类脚本:

import sys
class loader:
  def __init__(self, module_name, class_name): # both args are strings
    try:
      __import__(module_name)
      modul = sys.modules[module_name]
      instance = modul.class_name() # obviously this doesn't works, here is my main problem!
    except ImportError:
       # manage import error

some-dynamically-loaded-module script:

some-dynamically-loaded-module脚本:

class myName:
  # etc...

I use this arrangement to make any dynamically-loaded-module to be used by the loader-class following certain predefined behaviours in the dyn-loaded-modules...

我使用这种安排使装入器类使用的任何动态加载模块遵循动态加载模块中的某些预定义行为……

Any ideas are appreciated.

任何想法都是感激。

6 个解决方案

#1


163  

You can use getattr

您可以使用getattr

getattr(module, class_name)

to access the class. More complete code:

访问类。更完整的代码:

module = __import__(module_name)
class_ = getattr(module, class_name)
instance = class_()

As mentioned below, we may use importlib

如上所述,我们可以使用importlib

import importlib
module = importlib.import_module(module_name)
class_ = getattr(module, class_name)
instance = class_()

#2


91  

tl;dr

Import the module with importlib.import_module and load the class you need with getattr:

使用importlib导入模块。通过getattr加载需要的类:

# Standard import
import importlib
# Load "module.submodule.MyClass"
MyClass = getattr(importlib.import_module("module.submodule"), "MyClass")
# Instantiate the class (pass arguments to the constructor, if needed)
instance = MyClass()

explanations

You probably don't want to use __import__ to dynamically import a module by name, as it does not allow you to import submodules:

您可能不希望使用__import__按名称动态导入模块,因为它不允许您导入子模块:

>>> mod = __import__("os.path")
>>> mod.join
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'join'

Here is what the python doc says about __import__:

以下是python文档对__import__的描述:

Note: This is an advanced function that is not needed in everyday Python programming, unlike importlib.import_module().

注意:这是一个高级函数,与importlib.import_module()不同,在日常Python编程中不需要它。

Instead, use the standard importlib module to dynamically import a module by name. With getattr you can then instantiate a class by its name:

相反,使用标准的importlib模块,根据名称动态导入模块。通过getattr,您可以根据类的名称实例化类:

import importlib
my_module = importlib.import_module("module.submodule")
MyClass = getattr(my_module, "MyClass")
instance = MyClass()

You could also write:

你也可以写:

import importlib
module_name, class_name = "module.submodule.MyClass".rsplit(".", 1)
MyClass = getattr(importlib.import_module(module_name), class_name)
instance = MyClass()

This code is valid in python ≥ 2.7 (including python 3).

这段代码是有效的在python中≥2.7(包括python 3)。

#3


11  

Use getattr to get an attribute from a name in a string. In other words, get the instance as

使用getattr从字符串中的名称获取属性。换句话说,获取实例为

instance = getattr(modul, class_name)()

#4


9  

Copy-paste snippet:

复制粘贴代码片段:

def str_to_class(module_name, class_name)
    try:
        module_ = importlib.import_module(module_name)
        try:
            class_ = getattr(module_, class_name)()
        except AttributeError:
            logging.error('Class does not exist')
    except ImportError:
        logging.error('Module does not exist')
    return class_ or None

#5


5  

If you want this sentence from foo.bar import foo2 to be loaded dynamically, you should do this

如果你想从foo中得到这个句子。要动态加载bar import foo2,您应该这样做

foo = __import__("foo")
bar = getattr(foo,"bar")
foo2 = getattr(bar,"foo2")

instance = foo2()

#6


2  

I couldn't quite get there in my use case from the examples above, but Ahmad got me the closest (thank you). For those reading this in the future, here is the code that worked for me.

在上面的示例中,我不能很好地完成我的用例,但是Ahmad给了我最接近的(谢谢)。对于将来阅读本文的读者,以下是对我有用的代码。

def get_class(fully_qualified_path, module_name, class_name, *instantiation):
    """
    Returns an instantiated class for the given string descriptors
    :param fully_qualified_path: The path to the module eg("Utilities.Printer")
    :param module_name: The module name eg("Printer")
    :param class_name: The class name eg("ScreenPrinter")
    :param instantiation: Any fields required to instantiate the class
    :return: An instance of the class
    """
    p = __import__(fully_qualified_path)
    m = getattr(p, module_name)
    c = getattr(m, class_name)
    instance = c(*instantiation)
    return instance

#1


163  

You can use getattr

您可以使用getattr

getattr(module, class_name)

to access the class. More complete code:

访问类。更完整的代码:

module = __import__(module_name)
class_ = getattr(module, class_name)
instance = class_()

As mentioned below, we may use importlib

如上所述,我们可以使用importlib

import importlib
module = importlib.import_module(module_name)
class_ = getattr(module, class_name)
instance = class_()

#2


91  

tl;dr

Import the module with importlib.import_module and load the class you need with getattr:

使用importlib导入模块。通过getattr加载需要的类:

# Standard import
import importlib
# Load "module.submodule.MyClass"
MyClass = getattr(importlib.import_module("module.submodule"), "MyClass")
# Instantiate the class (pass arguments to the constructor, if needed)
instance = MyClass()

explanations

You probably don't want to use __import__ to dynamically import a module by name, as it does not allow you to import submodules:

您可能不希望使用__import__按名称动态导入模块,因为它不允许您导入子模块:

>>> mod = __import__("os.path")
>>> mod.join
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'join'

Here is what the python doc says about __import__:

以下是python文档对__import__的描述:

Note: This is an advanced function that is not needed in everyday Python programming, unlike importlib.import_module().

注意:这是一个高级函数,与importlib.import_module()不同,在日常Python编程中不需要它。

Instead, use the standard importlib module to dynamically import a module by name. With getattr you can then instantiate a class by its name:

相反,使用标准的importlib模块,根据名称动态导入模块。通过getattr,您可以根据类的名称实例化类:

import importlib
my_module = importlib.import_module("module.submodule")
MyClass = getattr(my_module, "MyClass")
instance = MyClass()

You could also write:

你也可以写:

import importlib
module_name, class_name = "module.submodule.MyClass".rsplit(".", 1)
MyClass = getattr(importlib.import_module(module_name), class_name)
instance = MyClass()

This code is valid in python ≥ 2.7 (including python 3).

这段代码是有效的在python中≥2.7(包括python 3)。

#3


11  

Use getattr to get an attribute from a name in a string. In other words, get the instance as

使用getattr从字符串中的名称获取属性。换句话说,获取实例为

instance = getattr(modul, class_name)()

#4


9  

Copy-paste snippet:

复制粘贴代码片段:

def str_to_class(module_name, class_name)
    try:
        module_ = importlib.import_module(module_name)
        try:
            class_ = getattr(module_, class_name)()
        except AttributeError:
            logging.error('Class does not exist')
    except ImportError:
        logging.error('Module does not exist')
    return class_ or None

#5


5  

If you want this sentence from foo.bar import foo2 to be loaded dynamically, you should do this

如果你想从foo中得到这个句子。要动态加载bar import foo2,您应该这样做

foo = __import__("foo")
bar = getattr(foo,"bar")
foo2 = getattr(bar,"foo2")

instance = foo2()

#6


2  

I couldn't quite get there in my use case from the examples above, but Ahmad got me the closest (thank you). For those reading this in the future, here is the code that worked for me.

在上面的示例中,我不能很好地完成我的用例,但是Ahmad给了我最接近的(谢谢)。对于将来阅读本文的读者,以下是对我有用的代码。

def get_class(fully_qualified_path, module_name, class_name, *instantiation):
    """
    Returns an instantiated class for the given string descriptors
    :param fully_qualified_path: The path to the module eg("Utilities.Printer")
    :param module_name: The module name eg("Printer")
    :param class_name: The class name eg("ScreenPrinter")
    :param instantiation: Any fields required to instantiate the class
    :return: An instance of the class
    """
    p = __import__(fully_qualified_path)
    m = getattr(p, module_name)
    c = getattr(m, class_name)
    instance = c(*instantiation)
    return instance