Dynamic Instantiation from String Name of a Class in Dynamically Imported Module

Dynamic instantiation from string name of a class in dynamically imported module?

You can use 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

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

How to instantiate class by it's string name in Python from CURRENT file?

If you are on the same module they are defined you can call globals(), and simply use the class name as key on the returned dictionary:

Ex. mymodule.py

class A: ...
class B: ...
class C: ...

def factory(classname):
cls = globals()[classname]
return cls()

Above solution will also work if you are importing class from another file

Otherwise, you can simply import the module itself inside your functions, and use getattr (the advantage of this is that you can refactor this factory function to any other module with no changes):

def factory(classname):
from myproject import mymodule
cls = getattr(mymodule, classname)
return cls()

How to instantiate class (implementation) base on input at runtime in Python

Maybe dynamic import can help you.

#importlib.import_module

You should ensure your file name and class name.

Then you can

import importlib

def get_obj(usr_input: str):
mod = importlib.import_module(usr_input)
usr_class = getattr(mod, usr_input)
return usr_class()

Above assump that your subclass's file name and class name are same as usr_input

Importing Python class by string

Your code is equivalent to:

from mymodule import MyClass

mymodule doesn't contain MyClass, so you will get an error. You want the equivalent of:

from mymodule.myclass import MyClass

That would be:

getattr(importlib.import_module('mymodule.MyClass'), 'MyClass')

Instantiate class dynamically with locate

Edit 2:

This solution will gather all classes available in the module the user provides, and then simply instantiates the first class.

import inspect
from pydoc import locate
name = "folder.subfolder.classname"
my_module = locate(name)

all_classes = inspect.getmembers(my_module, inspect.isclass)
if len(all_classes) > 0:
instance = all_classes[0][1]()

Edit:

Gathered from the comments I believe the following code will work for your use case:

from pydoc import locate
name = "folder.subfolder.classname"
my_module = locate(name)
class_name = name.rsplit('.')[-1]
my_class = getattr(my_module, class_name)
instance = my_class()

You do seem to be a bit confused as to what modules are which resulted in our miscommunication. class.py doesn't point to a class, but to a module. In that module (your class.py file) there can be multiple classes. For the answer above I just assume that in your class.py file you have a class with the same name as the file.

Original Answer:

Well as your error shows, your my_class variable is actually a module object. The name you provide doesn't actually point to your class but to the module containing the class.

To get a class from a module object by string you can do:

my_class = getattr(module, class_name)

and then like in your example code you can instantiate it like this:

instance = my_class()

To bring it all together:

module_name = "folder.subfolder.module_name"
my_module = locate(module_name)
my_class = getattr(my_module, class_name)
instance = my_class()

How do I dynamically change which class I'm accessing using a string in python?

You can use getattr to get an attribute dynamically. I believe this question already answered here Dynamic instantiation from string name of a class in dynamically imported module?

import myPythonFile

answer = str(input())
if answer == "yes":
classToAccess = "classA"
else:
classToAccess = "classB"

myVarible = getattr(myPythonFile, classToAccess).myVarible

Is it possible to dynamic instantiate a class written in a string without the need to write it to a file?

You just need to use exec: it supports dynamic execution of Python code.

import re 
def string_to_object(str_class, *args, **kwargs):
exec(str_class)
class_name = re.search("class ([a-zA-Z_][a-zA-Z0-9_]*)", str_class).group(1)
return locals()[class_name](*args, **kwargs)

You can use the string_to_object function to automatically create an object of the specified class:

my_class = '''
class A:
def print(self):
print("Hello World")
'''
a = string_to_object(my_class)
a.print() # Hello World

You can also build something more complicated:

my_class = '''
class B:
def __init__(self, a, b, c=0, d=1):
self.a = a
self.b = b
self.c = c
self.d = d
'''
b = string_to_object(my_class, 4, 5, c=7)
print(b.a) # 4
print(b.b) # 5
print(b.c) # 7
print(b.d) # 1

And also:

class C:
pass

my_class = '''
class D(C):
pass
'''

d = string_to_object(my_class)


Related Topics



Leave a reply



Submit