I need to understand how to script a batch change to bone constraints like copy location, limit distance etc.

I have a couple of hundred bones, with a set of constraints on them. It took forever to set up and I need to tweak them.

A friend who has written scripts for me before gave me a solution to one problem. I've tried adjusting the code he wrote to do something else but I've written something wrong. I don't know the syntax and proper context.

I tried changing my friend's code in the text editor:

import bpy

armature = "Armature.001"

arm = bpy.data.armatures[armature]

for bone in bpy.context.object.pose.bones:
    bone.bone.select = True
    arm.bones.active = bone.bone

for constraint in bpy.context.active_pose_bone.constraints:
    print (constraint)
   if "Copy YZ only" in constraint.name:
        CopyLocationConstraint.use_y = True


I understand what this SHOULD do but don't see the relevance of some of these lines of code. I need some assistance to find what I am missing.

The next bit I need to change is a distance value on transformation constraints (to_max_y = 2cm?). I guess the solution is similar but I need to learn how to word changes like this correctly.

I've spent hours reading examples online but still need help.

  • $\begingroup$ FYI, this is very close to what's called a "scripted rig." Scripted Rigs are a big deal in The Industry. Searching for those terms will help with your research, generally, but maybe not specifically with Blender. $\endgroup$
    – Matt
    May 26, 2016 at 20:55
  • $\begingroup$ Thank you for that Matt. This project has grown from a standard rig into something that requires scripting to be efficient. I do think that, going forward, learning to script it all is necessary. Would the term "scripted rig" refer to setting up bones and the constraints entirely via code? $\endgroup$
    – Chris Lee
    May 30, 2016 at 3:38

1 Answer 1


I'd go about it this way. I use context = bpy.context on test scripts, that can later be pasted into Operator or Panel code. Work from the context object, rather than using a name like "Armature.001" (guilty myself on many occasions)

I use list comprehension out of preference.

import bpy
context = bpy.context
# the rig object
rig = context.object

# all copy location constraints on all pose bones
constraints = [c for pb in rig.pose.bones 
                 for c in pb.constraints
                 if c.type == 'COPY_LOCATION'
               # and "XY" in c.name

# set the desired properties
for c in constraints:
    c.use_y = True

# similarly for Transformation
# type from mousing over add constraint in UI
constraints = [c for pb in rig.pose.bones 
                 for c in pb.constraints
                 if c.type == 'TRANSFORM'

for tc in constraints:
    tc.to_max_y = 0.02 # given 1 blender unit is 1m

# all constraints from preselected pose bones
constraints = [c for pb in context.selected_pose_bones 
                 for c in pb.constraints
  • $\begingroup$ Thank you @batFINGER, I did this with variations for a couple of constraints and it worked perfectly. Although the last part of the code got this error. TypeError: 'NoneType' object is not iterable $\endgroup$
    – Chris Lee
    May 30, 2016 at 3:44
  • $\begingroup$ As I am new to the coding side of things I would like to understand what the difference is between the method I was originally trying to adapt and list comprehension. $\endgroup$
    – Chris Lee
    May 30, 2016 at 3:49
  • $\begingroup$ One last question, as I want to learn how to script these changes, what do the following lines mean and where can I find some kind of tutorial or guidelines? "c for pb in rig.pose.bones" "for tc in constraints:" $\endgroup$
    – Chris Lee
    May 30, 2016 at 4:31
  • $\begingroup$ docs.python.org/3/tutorial/… $\endgroup$
    – batFINGER
    May 30, 2016 at 7:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .