Hi,<div><br></div><div>I'm trying to find a good way to control Blender from an external Python shell. I've spent a lot of time looking at past attempts and see that most haven't gone anywhere, as Blender's architecture seems to make this difficult. I tried to just have Python's InteractiveInterpreter class fed from a socket, but unfortunately Blender locks up completely while listening on the socket -- so it's not even able to come back into focus when I Alt-Tab to it. That's not really ideal, and so after reading the docs, it seems like the right way to do this is to have a modal operator on an event timer repeatedly grab input from a nonblocking socket, and feed *that* into InteractiveInterpreter. Unfortunately, the only code I've been able to cobble together for event timers seems to make blender unresponsive, and cause it to crash horribly. I've attached the code below, if anyone knows what's going on -- or has a better way to connect Blender to an external Python, I'd love to hear your thoughts. </div>
<div><br></div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><font face="courier new, monospace">import bpy</font></div></div><div><div><font face="courier new, monospace"><br></font></div>
</div><div><div><font face="courier new, monospace">class ModalOperator(bpy.types.Operator):</font></div></div><div><div><font face="courier new, monospace">    '''Operator which runs its self from a timer.'''</font></div>
</div><div><div><font face="courier new, monospace">    bl_idname = "wm.modal_operator"</font></div></div><div><div><font face="courier new, monospace">    bl_label = "Vertex Operator"</font></div></div>
<div><div><font face="courier new, monospace"><br></font></div></div><div><div><font face="courier new, monospace">    _timer = None</font></div></div><div><div><font face="courier new, monospace"><br></font></div></div><div>
<div><font face="courier new, monospace">    def modal(self, context, event):</font></div></div><div><div><font face="courier new, monospace">        print(event.type)</font></div></div><div><div><font face="courier new, monospace">        if event.type == 'ESC':</font></div>
</div><div><div><font face="courier new, monospace">            print("FINISHED")</font></div></div><div><div><font face="courier new, monospace">            context.window_manager.event_timer_remove(self._timer)</font></div>
</div><div><div><font face="courier new, monospace">            return {'FINISHED'}</font></div></div><div><div><font face="courier new, monospace">    <span class="Apple-tab-span" style="white-space:pre"> </span></font></div>
</div><div><div><font face="courier new, monospace">        if event.type == 'TIMER':</font></div></div><div><div><font face="courier new, monospace">            self.execute(context)</font></div></div><div><div><font face="courier new, monospace">            return {'RUNNING_MODAL'}</font></div>
</div><div><div><font face="courier new, monospace"><br></font></div></div><div><div><font face="courier new, monospace">    def execute(self, context):</font></div></div><div><div><font face="courier new, monospace">        print("EXC")</font></div>
</div><div><div><font face="courier new, monospace">        bpy.ops.object.mode_set(mode='EDIT')</font></div></div><div><div><font face="courier new, monospace">        context.window_manager.modal_handler_add(self)</font></div>
</div><div><div><font face="courier new, monospace">        self._timer = context.window_manager.event_timer_add(0.1, context.window)</font></div></div><div><div><span class="Apple-tab-span" style="white-space:pre"><font face="courier new, monospace">   </font></span></div>
</div><div><div><font face="courier new, monospace">bpy.utils.register_class(ModalOperator)</font></div></div><div><div><font face="courier new, monospace">bpy.ops.wm.modal_operator('INVOKE_DEFAULT')</font></div></div>
</blockquote><div><br></div>