Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get python class object from string [duplicate]

Tags:

python

Possible Duplicate:
Dynamic module import in Python

Probably a simple question! I need to iterate through a list of classes (as strings) passed from a settings file. The classes are listed like below:

TWO_FACTOR_BACKENDS = (
    'id.backends.AllowToBeDisabled', # Disable this to enforce Two Factor Authentication
    'id.backends.TOTPBackend',
    'id.backends.HOTPBackend',
    #'id.backends.YubikeyBackend',
    #'id.backends.OneTimePadBackend',
    #'id.backends.EmailBackend',
)

I now need to call the authenticate() function on each of these classes (unless commented out, of course). I'm happily iterating through the list, I just need to know how to convert the strings to a Class object in my foreach loop so that I can call the authenticate method on it. Is there an easy way to do this?

like image 679
TC Fox Avatar asked May 27 '12 10:05

TC Fox


People also ask

How do I return a copy of a class object in Python?

To get a fully independent copy of an object you can use the copy. deepcopy() function.

How do you copy an object from a string in Python?

In Python, we use = operator to create a copy of an object.

Can you copy an instance of a class in Python?

Yes, you can use copy. deepcopy . so just c2 = copy.

How an object is copied in Python?

In the case of shallow copy, a reference of an object is copied into another object. It means that any changes made to a copy of an object do reflect in the original object. In python, this is implemented using the “copy()” function.


1 Answers

You want to use the importlib module to handle loading of modules like this, then simply use getattr() to get the classes.

For example, say I have a module, somemodule.py which contains the class Test:

import importlib

cls = "somemodule.Test"
module_name, class_name = cls.split(".")

somemodule = importlib.import_module(module_name)

print(getattr(somemodule, class_name))

Gives me:

<class 'somemodule.Test'>

It's trivial to add in things like packages:

cls = "test.somemodule.Test"
module_name, class_name = cls.rsplit(".", 1)

somemodule = importlib.import_module(module_name)

And it will not import a module/package if it's already been imported, so you can happily do this without keeping track of loading modules:

import importlib

TWO_FACTOR_BACKENDS = (
    'id.backends.AllowToBeDisabled', # Disable this to enforce Two Factor Authentication
    'id.backends.TOTPBackend',
    'id.backends.HOTPBackend',
    #'id.backends.YubikeyBackend',
    #'id.backends.OneTimePadBackend',
    #'id.backends.EmailBackend',
)

backends = [getattr(importlib.import_module(mod), cls) for (mod, cls) in (backend.rsplit(".", 1) for backend in TWO_FACTOR_BACKENDS)]

 

like image 182
Gareth Latty Avatar answered Sep 18 '22 17:09

Gareth Latty