3
$\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$

1 Answer 1

6
$\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$

You must log in to answer this question.

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