[Bug] [bpy] Vertex not in group error when setting vertex group weight

OS version is OS X 10.12.2, Blender version is 2.77

After several days of trying to solve this problem, I’m stuck. I wrote a script that takes two objects and copies the vertex weights from a vertex on one to the other if they share the same position, but only for vertices group that share names. I’ve gotten rid of all the errors except for one that says “Error: Vertex not in group” when I call access the weight of a vertex from the first group using the index of the vertex. This really makes no sense since I’m using the index of the vert from the mesh, and it’s acting as if the vertex doesn’t exist.

import bpyimport mathutils


def CopyVertexWeightIfVertsShareSamePosition(objectToCopyFromName, objectToCopyToName):
    
    objectToCopyFrom = bpy.data.objects.get(objectToCopyFromName)
    objectToCopyTo = bpy.data.objects.get(objectToCopyToName)
    
    #check to see if both objects exist, checks are omitted for ease 
    #check to see if bother objects are meshes
    
    dataToCopyFrom = bpy.data.meshes.get(objectToCopyFrom.data.name)
    dataToCopyTo = bpy.data.meshes.get(objectToCopyTo.data.name)
    
    fromObjectGroupNames = objectToCopyFrom.vertex_groups.keys()
    toObjectGroupNames = objectToCopyTo.vertex_groups.keys()
    
    #check to see if both objects have vertex groups
    
    sharedNames = []
    
    for i in fromObjectGroupNames:
        for j in toObjectGroupNames:
            if i == j:
                sharedNames.append(j)
    
    #check to see if both objects have grous the share names
    
    for firstVert in dataToCopyFrom.vertices:
        for secondVert in dataToCopyTo.vertices:
            
            if (mathutils.Vector(objectToCopyFrom.location) - mathutils.Vector(objectToCopyTo.location)) + mathutils.Vector(firstVert.co) == mathutils.Vector(secondVert.co):
                
                for g in sharedNames:
                    
                    firstVgroup = objectToCopyFrom.vertex_groups.get(g)
                    secondVgroup = objectToCopyTo.vertex_groups.get(g)
                    
                    print("Weight of first vert: {0}".format(firstVgroup.weight(firstVert.index)))#here's the problem
                    secondVgroup.add(secondVert.index, firstVgroup.weight(firstVert.index), 'REPLACE')

I’ve included few comments, but do keep in mind I’m not a big Python fan so most of what I say is probably completely wrong. However, I always write like I know exactly what the hell I’m talking about. :yes::no:



import bpy
import mathutils




def CopyVertexWeightIfVertsShareSamePosition(objectToCopyFromName, objectToCopyToName):


    objectToCopyFrom = bpy.data.objects.get(objectToCopyFromName)
    objectToCopyTo = bpy.data.objects.get(objectToCopyToName)


    #check to see if both objects exist, checks are omitted for ease 
    #check to see if bother objects are meshes
    
    # We've now got references to the objects. So as long as we've checked they are of type 'MESH'
    # then:
    dataToCopyFrom = objectToCopyFrom.data
    dataToCopyTo = objectToCopyTo.data
    #dataToCopyFrom = bpy.data.meshes.get(objectToCopyFrom.data.name)
    #dataToCopyTo = bpy.data.meshes.get(objectToCopyTo.data.name)
    
    fromObjectGroupNames = objectToCopyFrom.vertex_groups.keys()
    toObjectGroupNames = objectToCopyTo.vertex_groups.keys()
    
    #check to see if both objects have vertex groups
    
    sharedNames = []
    
    for i in fromObjectGroupNames:
        for j in toObjectGroupNames:
            if i == j:
                sharedNames.append(j)


    #check to see if both objects have grous the share names


    for firstVert in dataToCopyFrom.vertices:
        for secondVert in dataToCopyTo.vertices:


            # Vector data type properties return copies of their vectors not references 
            # so there is no need to be duplicating what has already been duplicated.
            #
            # So objects have to be at the same location but what about rotation and scale?
            # maybe you really want to be doing: 
            #if objectToCopyFrom.matrix_world * firstVert.co == objectToCopyTo.matrix_world * secondVert.co:
            if (objectToCopyFrom.location - objectToCopyTo.location) + firstVert.co == secondVert.co:


                for g in sharedNames:


                    # It's always better for debugging to NOT use get when you are
                    # sure that it exists i.e. you are not checking for a 'None' value return type.
                    firstVgroup = objectToCopyFrom.vertex_groups[g]
                    secondVgroup = objectToCopyTo.vertex_groups[g]


                    # Vertex groups hold indices to the Blender vertices list that way they don't 
                    # need to hold a complete list of weights for all vertices and can saves on memory. 
                    # when you call the weight function using a vertex index that isn't in the vertex group
                    # Blender throws the error "Vertex not in group"
                    #
                    # I'm sure this could be done better but It's just checking if the vertex is assigned 
                    # to the group.
                    vert_grp = [g for g in firstVert.groups if g.group == firstVgroup.index]
                    if len(vert_grp):
                        #you could actually use 'vert_grp[0].weight' instead of firstVgroup.weight(firstVert.index)
                        print("Weight of first vert: {0}".format(firstVgroup.weight(firstVert.index)))#here's the problem


                        # Error! It was expecting a sequence of vertex indices not an integer. 
                        # Note! It maybe faster to created the lists first and then call add function at the end.
                        secondVgroup.add([secondVert.index], firstVgroup.weight(firstVert.index), 'REPLACE')


                #can there be more than one vertex at the same location? if not:
                #break 


if __name__ == "__main__":
    active_ob = bpy.context.active_object
    selected = bpy.context.selected_objects
    sel = [ob for ob in selected if ob != active_ob]
    
    for ob in sel:
        CopyVertexWeightIfVertsShareSamePosition(active_ob.name, ob.name)

I really think you’re selling yourself short, because after I put in the changes you suggested, everything is working like it’s meant to. I actually had no idea that you could access the entries in vertex_groups as a list. Thanks you for your help.