# set a property via its data path stored in a string

I have a property called A

I have another property called ADP that stores the data path of A as a string

How can I use the string data path to set property A?

I could add "= myvar" to the end of the string and use exec on the new string but that's overkill I think.

• What's the purpose of storing a data path in a property to another property? – CodeManX Apr 18 '14 at 1:00
• I have a UI that the user can paste a data path into, its then stored as a string. like when you add a var to a driver – MCHammond Apr 18 '14 at 1:03
• I suppose I should add that the property could be anything that can have a data path: "pose.bones["Bone"].location.x" or "pose.bones["Bone"].constraints["IK"].influence" – MCHammond Apr 18 '14 at 1:06
• You could recursively getattr() and stop on e.g. Vectors, otherwise you will end up with a float value, which isn't writeable. Object.path_resolve() has a similar issue, "location.x" will return a value and you can't assign to it. exec() doesn't seem so bad with this in mind... – CodeManX Apr 18 '14 at 2:00
• Im looking at using bpy.ops.wm.context_set_float() it works but floods the console with errors if its a vector3 ie rotation_euler.x, any idea? – MCHammond Apr 18 '14 at 2:02

To set a property you only have as a string, you can use Python's setattr()

import bpy
obj = bpy.context.object

# regular method
obj.location = 1, 2, 3

# using setattr
setattr(obj, "location", (1, 2, 3))


Notice setattr takes a string, so this can come from anywhere you like.

For simple properties, this works fine, however, if you want to set a path with multiple elements this becomes more complicated.

eg: modifiers["Subsurf"].levels

In this case there isn't such a clean solution.

There is a blender specific function called bpy_struct.path_resolve. Internally this uses the same method which is used to resolve FCurve and driver paths.

You could define a function for setting the attribute that combines path_resolve and setattr:

def value_set(obj, path, value):

if "." in path:
# gives us: ('modifiers["Subsurf"]', 'levels')
path_prop, path_attr = path.rsplit(".", 1)

# same as: prop = obj.modifiers["Subsurf"]
prop = obj.path_resolve(path_prop)
else:
prop = obj
# single attribute such as name, location... etc
path_attr = path

# same as: prop.levels = value
setattr(prop, path_attr, value)

# example usage (requires path_resolve)
value_set(bpy.context.object, 'modifiers["Subsurf"].levels', 2)

# example usage (uses simple setattr)
value_set(bpy.context.object, 'location', (1, 2, 3))


However this is a bit involved, you could just do...

exec("obj" + path + " = value")


Though using exec is not ideal, especially if you don't know where the inputs come from. (security considerations)

Note: even though the example uses bpy.context.object you could use a Scene, Group, Mesh, Modifier... any Blender data really.