Invoke a .py script with a button on the tools panel I have this script - rather lengthy - that creates simple skin, eyes and mouth shaders for figures imported into Blender from Poser. I wish to create a panel/addon (something!) that does the following things:


set the path to the image files used in the shaders 
define via dropdown the core figure type
pass this data on to the script, and save this info somewhere
have a button on the panel actually invoke running the script


I have looked at example scripts (the templates) but they all involve in-built operators that do things directly to mesh. Given this appears to be the predominant use of panel tools, I'm wondering if I should use a panel for this purpose or if another mechanism would be more appropriate.

Here is what I have so far... the panel code:

import bpy

class MatShaderInfoPanel(bpy.types.Panel):
    """Create shaders for your Poser figure: Panel"""
    bl_label = "Figure Files Info"
    bl_idname = "MATERIALS_PT_shaders"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Skin Shaders"

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

    obj = context.object

    row = layout.row()
    row.label(text='Figure Name')

    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", text='Find Images', icon='FILESEL')
    row = layout.row()
    row.operator("object.runScript", text = 'Apply Shaders')
def register():
    bpy.utils.register_class(MatShaderInfoPanel)


...and the custom operator (as kindly suggested by m.ardito in the link provided below):

import bpy

def main(context):
    filename = 'Shaders034.py'
    exec(compile(open(filename).read(), filename, 'exec'))

class runScript(bpy.types.Operator):
    """Tooltip"""
    # was bl_idname = "object.run_script" - is now:
    bl_idname = "object.runScript"
    bl_label = "Invokes a Script"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        main(context)
        return {'FINISHED'}

def register():
    bpy.utils.register_class(runScript)
def unregister():
    bpy.utils.unregister_class(runScript)
if __name__ == "__main__":
    register()


When I try to run the panel code, I get a slew of the following error messages:


  rna_uiItemO: operator missing srna 'object.runScript'
  /home/robyn/Documents/Blender/Projects/AllScripts/Shader_blend/skinShader034.blend/MatShader_panel.py:28


...and this bit:

row = layout.row()
row.operator("object.runScript", text = 'Apply Shaders')


...doesn't end up displaying anything on the panel. I'm clearly missing a step.
The following works for me:

import bpy

class MatShaderInfoPanel(bpy.types.Panel):
    """Create shaders for your Poser figure: Panel"""
    bl_label = "Figure Files Info"
    bl_idname = "MATERIALS_PT_shaders"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Skin Shaders"

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

        obj = context.object

        row = layout.row()
        row.label(text='Figure Name')

        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", text='Find Images', icon='FILESEL')
        row = layout.row()
        row.operator("object.run_script", text = 'Apply Shaders')

class runScript(bpy.types.Operator):
    """Tooltip"""
    # was bl_idname = "object.run_script" - is now:
    bl_idname = "object.run_script"
    bl_label = "Invokes a Script"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        print('Yay!')

        return {'FINISHED'}

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

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

if __name__ == "__main__":
    register()