2
$\begingroup$

In a project I have a very simple application handler that is executed when the current frame change:

import bpy

def frame_handler(scene):
    print("Running frame handler version 1.")

if frame_handler in bpy.app.handlers.frame_change_pre:
    print("Removing handler")
    bpy.app.handlers.frame_change_pre.remove(frame_handler)

print("Adding handler")
bpy.app.handlers.frame_change_pre.append(frame_handler)

print("Number of handlers: " + str(len(bpy.app.handlers.frame_change_pre)))

Adding the handler works fine and it’s executed as expected. But let’s says I want to update my handler to version 2. If I change to the code and run it again I will now have two handlers. When the handler is executed I see that both the old and the new version was running.

In my script I have tried to detect and existing handler and remove it, but clearly that doesn’t work. How do I do that?

My best solution so far is to execute bpy.app.handlers.frame_change_pre.clear() but that feels like cheating :-)

I’m using Blender 2.80 RC3.

$\endgroup$
5
$\begingroup$

Look at the function names and modules

If a function added to handler has a namespace it can be removed quite simply, as shown in the register and unregister methods in and addon.

def foo():
    print("bar")

def register():
    handers.append(foo)

def unregister():
    handlers.remove(foo)

if __name__ == "__main__":
    register()

The method has that import scope., if however it is added in main thread via a test script then editing to call unregister, rather than register,

if __name__ == "__main__":
    unregister()

foo now compared to then is a totally different foo and will throw an error

Recommend looking at the functions name instead.

EDIT the module f.__module__ tested against __name__ would be the ideal way to remove these.

# handlers added to main thread 

my_handlers = [h for h in bpy.app.handlers.frame_change_pre
    if h.__module__ == "__main__"]

The old code uses a test on the functions names.

import bpy

def foo(scene):
    pass

for i in range(4):
    bpy.app.handlers.frame_change_pre.append(foo)

# handlers named "foo"

foo_handlers = [h for h in bpy.app.handlers.frame_change_pre
        if h.__name__ == "foo"]

print(foo_handlers)

for f in foo_handlers:
    bpy.app.handlers.frame_change_pre.remove(f)

foo_handlers = [h for h in bpy.app.handlers.frame_change_pre
        if h.__name__ == "foo"]

print(foo_handlers)

I often use some silly prefix like def ST_____foo(): and remove all handlers with if f.__name__.startswith("ST____")

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.