0

I would like to transform a tuple:

TEST_CLASSES = (
   'common.test.TestClass',
)

to

TEST_CLASSES = {
   'test': common.test.TestClass,
}

How to make a dictionary is simple but I have a problem with conversion from string to object. Could anybody help me please? thanks!

  • i think this is a similar question http://stackoverflow.com/questions/452969/does-python-have-an-equivalent-to-java-class-forname – Dyno Fu Feb 09 '10 at 11:55
  • As far as I understand, you try to get class by its string name. There were similar questions: http://stackoverflow.com/questions/547829/how-to-dynamically-load-a-python-class, http://stackoverflow.com/questions/452969/does-python-have-an-equivalent-to-java-class-forname – Rorick Feb 09 '10 at 11:59

4 Answers4

1

You could use eval, which can be evil if your inputs are not safe:

>>> import os
>>> eval('os.path.join')
<function join at 0x00BBA2B8>

if the common.test.TestClass doesn't exist in the current namespace a NameError will be raised:

>>> eval('math.isnan')
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    eval('math.isnan')
  File "<string>", line 1, in <module>
NameError: name 'math' is not defined
SilentGhost
  • 307,395
  • 66
  • 306
  • 293
1

As far as I understand, you try to get class by its string name. There was a similar question: How to dynamically load a Python class

Community
  • 1
  • 1
Rorick
  • 8,857
  • 3
  • 32
  • 37
0

You can't directly "convert from string to object" (though in a technical sense, strings are objects), but you can use a function that can import the objects for you. Werkzeug's werkzeug.utils module has a function in it named import_string that does just that (source here).

(I'm assuming that the objects you want are to be imported from modules.)

So, if you use a similar import_string function, you can transform the tuple to a dictionary with this:

test_classes = {}
for path in TEST_CLASSES:
    obj = import_string(path)
    test_classes[obj.__module__.split('.')[-1]] = obj
LeafStorm
  • 3,057
  • 4
  • 24
  • 28
0

The straightforward and oftenly not recomended way there is to use "eval".

Simply doing:

obj = eval('common.test.TestClass') 

Will give you the object as specified on the string.

Other, more elegant ways, would involve querying each object on the chain for the next attribute - you can avoud eval in this way:

string = 'common.test.TestClass'

# this retrieves the topmost name, supposedly a module, as an object:
obj = globals()[string.split(".")[0]]

# And retrieve each subobject object therein:
for part in string.split(".")[1:]:     
    obj = getattr(obj, part)

If part of your object path is an yet not-imported submodule, though, this won't work - You'd have to "exec" an import statement to retrieve the module - Exec being a "stronger" form of eval, wich supports statements, while eval is reserved only for expressions.

jsbueno
  • 99,910
  • 10
  • 151
  • 209