Problem with for loop in vertices I want to add an empty to each vertex of my model but sometimes it works and sometimes there's an error ("Requires selected vertices or active vertex group"). However this error appears after the loop is running the 10th time or so; So, this is completely confusing...

Where's the problem with my code?

import bpy

#CREATE GROUP FOR STICKY EMPTIES
bpy.ops.group.create(name="sticky_grp")

#ACTIVE OBJECT
actObj = bpy.context.active_object

#VERTICE ARRAY OF THE ACTIVE OBJECT
actVerts = actObj.data.vertices

#COUNT FOR NAMESPACES IN LOOP
cnt = 0

#FOR LOOP TO GET VERTICES AND SET "a" AS VERTEX VARIABLE
for a in actVerts:

    bpy.ops.object.mode_set(mode='OBJECT')                   #SWITCH TO OBJECT MODE
    a.select = True                                          #SELECT VERTEX
    bpy.ops.object.mode_set(mode='EDIT')                     #SWITCH TO EDIT MODE
    bpy.ops.object.hook_add_newob()                          #CREATE HOOK TO SELECTED   VERTEX
    bpy.context.selected_objects[0].name = "sticky_empty"    #RENAME EMPTY TO STICKY EMPTY
    bpy.ops.mesh.select_all(action='DESELECT')               #DESELECT VERTICES

    #SELECT STICKY EMPTY
    try:
        if cnt == 0:
            bpy.data.objects['sticky_empty'].select
            bpy.ops.group.objects_add_active(group = 'sticky_grp')

        elif 1 &lt;= cnt &lt; 10:
            bpy.data.objects['sticky_empty.00' + str(cnt)]
            bpy.ops.group.objects_add_active(group = 'sticky_grp')

        elif 10 &lt;= cnt &lt; 100:
            bpy.data.objects['sticky_empty.0' + str(cnt)]
            bpy.ops.group.objects_add_active(group = 'sticky_grp')

        else:
            bpy.data.objects['sticky_empty.' + str(cnt)]
            bpy.ops.group.objects_add_active(group = 'sticky_grp')
    except:
        print("SELECT STICKY EMPTY ERROR")  


    #DELETE HOOK MODIFIER
    try:
        if cnt == 0:
            bpy.ops.object.modifier_remove(modifier="Hook-Empty")

        elif 1 &lt;= cnt &lt; 10:
            bpy.ops.object.modifier_remove(modifier="Hook-Empty.00" + str(cnt))

        elif 10 &lt;= cnt &lt; 100:
            bpy.ops.object.modifier_remove(modifier="Hook-Empty.0" + str(cnt))

        else:
            bpy.ops.object.modifier_remove(modifier="Hook-Empty." + str(cnt))
    except:
        print("DELETE HOOK MODIFIER ERROR") 

    #ADD NAMESPACE + 1         
    cnt = cnt + 1 
    print(a)
You have to toggle out of edit mode after deselecting all vertices to solve your issue.

bpy.ops.object.mode_set(mode='OBJECT')          #SWITCH TO OBJECT MODE
a.select = True                                 #SELECT VERTEX
bpy.ops.object.mode_set(mode='EDIT')            #SWITCH TO EDIT MODE 
bpy.ops.object.hook_add_newob()
bpy.ops.mesh.select_all(action='DESELECT')      #DESELECT VERTICES
bpy.ops.object.editmode_toggle()                


For better understanding why you have to leave the edit mode this answer maybe helps.



Edit: In terms of better error handling I suggest you to write a bit more functional and split the code in useful pieces. The positive side effect would be that you have much more control, because you also can cache your states. I assume from the code above you want to have following functions:


create empties from all verticies of the selected object
add and assign hook modifiers for all empties to the selected object
create a group or add empties to a group


For e.g. this function creates the empties and returns a list of the new ones:

# -----------------------------------------------------------------------
# create empties from vertices
# -----------------------------------------------------------------------
# parameter: mesh object
# returns: list of new empty objects

def createEmptiesFromVerts (obj):

    # get object data
    objMesh = obj.data
    vertList = [vert for vert in objMesh.vertices]

    # create a list for the new empties
    emptyList = []

    for i in range(len(vertList)):

        # get local coordinate
        vertCoordinate = obj.data.vertices[i].co
        vertCoordinate = obj.matrix_world * vertCoordinate

        # add the empty    
        bpy.ops.object.add(type='EMPTY', location=vertCoordinate)
        newEmpty = bpy.context.active_object
        newEmpty.location = vertCoordinate
        newEmpty.empty_draw_size = newEmpty.empty_draw_size # / 4
        bpy.ops.object.select_all(action='TOGGLE')
        bpy.ops.object.select_all(action='DESELECT')

        # append the new empty to the list
        emptyList.append(newEmpty)

    # set object to original state
    bpy.context.scene.objects.active = obj
    obj.select = True

    # return the new empties  
    return emptyList


With this incoming list you can go on with the next function and assign the hook modifiers.

# -----------------------------------------------------------------------
# create hook modifiers
# -----------------------------------------------------------------------
# parameter: mesh object, hook object list
# returns: assigned hooks list, assigned modifier list

def hooksFromVerts (obj, hookObjs):

    # get object data
    objMesh = obj.data
    vertList = [vert for vert in objMesh.vertices]

    # create list to save all assigned hooks
    assignedHooks = []
    assignedModifiers = []

    for i in range(len(vertList)):

        bpy.ops.object.mode_set(mode="EDIT")
        bpy.ops.mesh.select_all(action="DESELECT")
        bpy.context.tool_settings.mesh_select_mode = (True , False , False)
        bpy.ops.object.mode_set(mode="OBJECT")

        # get local coordinate of vertex
        vertCoordinate = obj.data.vertices[i].co
        vertCoordinate = obj.matrix_world * vertCoordinate

        bpy.context.object.data.vertices[i].select = True
        bpy.ops.object.mode_set(mode="EDIT")

        # assign hook if coords of vert and hook object are equal
        for n in hookObjs:
            if vertCoordinate == n.location:
                #modifierName = "Hook" + str(i+1)
                modifierName = "Hook_" + n.name
                obj.modifiers.new(modifierName, type='HOOK')
                obj.modifiers[modifierName].object = n
                bpy.ops.object.hook_assign(modifier=modifierName)

                # append the hook objects to the list
                assignedHooks.append(n)

                # append modifiers
                assignedModifiers.append(modifierName)

    # set object to original state    
    bpy.ops.mesh.select_all(action = 'DESELECT')
    bpy.ops.object.mode_set(mode ="OBJECT")

    # set object to original state
    bpy.context.scene.objects.active = obj
    obj.select = True

    # return assogned hooks objects and modifiers
    return assignedHooks, assignedModifiers


As last step you can create a function that creates a group if it not exists and throw your empties in it. To call this is much more easier and for us more readable at all:

# get the object
selectedObj = bpy.context.active_object

if selectedObj.type == 'MESH':

    # create empties
    generatedEmpties = createEmptiesFromVerts(selectedObj)

    # create hooks
    generatedHooks = hooksFromVerts(selectedObj, generatedEmpties)

    # remove modifiers
    #removeModifiersByNameList(selectedObj, generatedHooks[1])

    # create or add to group
    generatedGroup = addObjectsToGroup("testgroup", generatedHooks[0])

else:
    print ("please select a mesh object.")


Hope this helps!