Add-On Dev: Per-File Initialization (Issues Enabling Add-on After File Load)
Add-ons can do per-file initialisation, if the add-on has some kind of panel in the UI somewhere.

You may notice various panels in Blender's UI have checkboxes next to the panel title. This is can be because they don't want to be active unless specifically turned on, but it can also be because they want to do some setup before being used:



This can be achieved in your own add-on by adding a draw_header function into the class that defines your panel:

def draw_header(self, context):

    self.layout.prop(context.scene, "addon_panel_enabled", text="")


The draw_header displays a boolean which I created and registered in the register function of the add-on:

bpy.types.Scene.addon_panel_enabled = bpy.props.BoolProperty(default=False, update=initialiseAddon)


The property has an update function called initialiseAddon which runs when the boolean is changed. It is in initialiseAddon that you can run your setup code.

Be aware, however, that this will run when the header checkbox is enabled and disabled. You could of course include code to make sure it only runs once by checking if the header boolean is true (the update function seems to be run after the value has been set):

def initialiseAddon(self, context):
    if context.scene.addon_panel_enabled:
        print("Only runs when enabling the checkbox")


Or just make another property which stores whether initialisation has been done or inspect your own data.

If you don't have a panel, then you should do initialisation in your operator when it first runs and again, have a scene property that stores whether setup has been done or not.

Full code (based on the UI Panel Simple template that comes with Blender):

import bpy

class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw_header(self, context):

        self.layout.prop(context.scene, "addon_panel_enabled", text="")

    def draw(self, context):
        layout = self.layout

        obj = context.object

        row = layout.row()
        row.label(text="Hello world!", icon='WORLD_DATA')

        row = layout.row()
        row.label(text="Active object is: " + obj.name)
        row = layout.row()
        row.prop(obj, "name")

        row = layout.row()
        row.operator("mesh.primitive_cube_add")

def initialiseAddon(self, context):
    #Per file initialisation code here
    if context.scene.addon_panel_enabled == True:
        print("Only runs when enabling the checkbox")

def register():
    bpy.types.Scene.addon_panel_enabled = bpy.props.BoolProperty(default=False, update=initialiseAddon)
    bpy.utils.register_class(HelloWorldPanel)

def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)
    del bpy.types.Scene.addon_panel_enabled

if __name__ == "__main__":
    register()