# Multi-File Packages need to unregister all classes from files

Blender (2.70a) is crashing with segmentation faults when I enable/disable/reenable my addon. I've inherited a project with a multi-file package design. I'm suspect that some classes are not unregistering since they aren't being called when the addon's unregister gets called.

I've reviewed this cookbook. And in both examples there are no bpy.type.Operators except in the __init__.py file. But in my project some files have Operators and Panels and some don't.

Does anyone know if reregistering classes can cause a crash? What's the point of calling bpy.utils.unregister_module(__name__) if it doesn't unregister. Here is my __init__.py

bl_info = {
'name': 'MyTools',
'author': 'Me',
'version': (0, 3),
'blender': (2, 69, 0),
'location': 'bpy.ops.mytools',
'description': 'MyTools',
'warning': '',
'wiki_url': '',
'category': 'user'}

import os
import sys
import importlib

# import/reload all .py files dynamically
for file_name in os.listdir(os.path.dirname(__file__)):
if file_name      == '__init__.py' or \
file_name[-3:] != '.py'         or \
file_name[0]   == '.'           or \
file_name[0]   == '#':
continue

module_name = 'mytool.' + file_name[:-3]
__import__(module_name, locals(), globals())

module = sys.modules[module_name]
if 'bpy' in locals():
print(module.__name__)

if 'bpy' in locals():
else:

import bpy

def register():
bpy.utils.register_module(__name__)

def unregister():
bpy.utils.unregister_module(__name__)

if __name__ == '__main__':
register()


And mock up of one of the other files. foo.py

from . import myUtils

import bpy

class myOp(bpy.types.Operator):
bl_idname = "mytools.myop"
bl_label = "my operator"
def execute(self,context):
self.report({'INFO'}, "awesome")
return {'FINISHED'}

bpy.utils.register_class(myOp)


Is this as simple as adding register and unregister methods to all of my other .py files.

• The way you import the other files looks really odd. Why don't you use a more common way to import, that doesn't walk the directory? I'm not sure if this is causing the crashes however. – CoDEmanX Apr 30 '14 at 0:57
• This is what I inherited. I'm trying not to have to refactor too much. The idea is to not have to edit the init.py every time you need to add file. – Ben L Apr 30 '14 at 1:30
• Did I mention that Blender is crashing like crazy? – Ben L Apr 30 '14 at 22:11

If there are any custom PropertyGroup classes in the submodules, they have to be loaded in the correct order. You also need to "unregister" the submodules.

This is a pattern in the main file

def register():
#register operators and propertyGroups explicitly
bpy.utils.register_class(myPGClass1)
#and/or run a helper function that finds all the classes and registers them

bpy.utils.register_module(__name__)

bpy.types.Scene.myTool = bpy.props.PointProperty(type=myPGClass1)

def unregister():

#important: delete custom schema
del bpy.types.Scene.myTool
#unregister_classes, or use helper
bpy.utils.unregister_class(myPGClass1)
bpy.utils.unregister_module(__name__)

if __name__ == '__main__':
register()


The this should work find if everything is in the __init__.py file. But since this is not the case, then these are the issues I discovered.

1. register_module() just finds the bpy.types.* classes in the module and runs register_class which looks to be a python call into C. So this doesn't look in the other files. So one has to call register_class on anything defined there.

2. enabling and disabling scripts will find the register and unregister functions by duck-typing. But only the __init__.py file will be in the list that gets checked. So anything in unregister() will not get called. This is the del types.myType line.

3. even though registering and unregistering is not working. Reloading will import the submodules, thus causing erratic behavior and classes will be reregistering, and the schema will try to update from a dereferenced raw pointer.