Cannot unsubscribe function from bpy.msgbus
Owner can be any python object.+

Using example here https://developer.blender.org/P563 can use the simple python object class to instance a handle.

handle = object()


Can also use

handle = 4
handle = set()


Simple example throws callback when context object name is changed.  Running in  text editor (main thread) the handle is lost. A quick workaround is to  save it to the driver namespace.

import bpy

handle = object()

# all branches below work
if 1:
    # To get some properties we need to prevent them being coerced into native Py types.
    subscribe_to = bpy.context.object.path_resolve("name", False)
elif 0:
    subscribe_to = bpy.context.object.location
else:
    # all object locations
    subscribe_to = bpy.types.Object, "location"

def notify_test(*args):
    print("Notify changed!", args)

bpy.msgbus.subscribe_rna(
    key=subscribe_to,
    owner=handle,
    args=(1, 2, 3),
    notify=notify_test,
)

# In general we won't need to explicitly publish, nevertheless - support it.
bpy.msgbus.publish_rna(key=subscribe_to)
bpy.app.driver_namespace["handle"] = handle
# ... to clear
# bpy.msgbus.clear_by_owner(handle)


To clear the callback via python console

&gt;&gt;&gt; bpy.msgbus.clear_by_owner(
clear_by_owner(owner)
.. function:: clear_by_owner(owner)
Clear all subscribers using this owner.
&gt;&gt;&gt; bpy.msgbus.clear_by_owner(bpy.app.driver_namespace['handle'])


If an immutable type like int is used (eg handle = 4 can clear from console with

bpy.msgbus.clear_by_owner(4)


but not for a dict handle = {}, possible the hassle in question code when setting the scene ID property.

In an addon can define the handle globally and remove in the unregister method, as it has the addon's module scope.

handle = object()

def register():
    # set up a callback with owner = handle

def unregister():
    bpy.msgbus.clear_by_owner(handle)