Using Wing with Modo

Index of All Documentation » How-Tos » How-Tos for Modeling, Rendering, and Compositing Systems »


Wing Pro Screenshot

Wing Pro is a Python IDE that can be used to develop, test, and debug Python code written for Modo, a commercial 3D modeling, animation, texturing, and rendering application..

If you do not already have Wing Pro installed, download it now.

This document describes how to configure Wing for Modo. To get started using Wing as your Python IDE, please refer to the tutorial in Wing's Help menu or read the Quickstart Guide.

Debugging Setup

When debugging Python code running under Modo, the debug process is initiated from outside of Wing, and must connect to the IDE. This is done with wingdbstub according to the detailed instructions in the Debugging Externally Launched Code section of the manual. In summary, you will need to:

  • Copy wingdbstub.py from your Wing installation into a directory that will be on the sys.path when Python code is run by Modo. You may need to inspect that (after import sys) first from Modo, or you can add to the path with sys.path.append() before importing wingdbstub.
  • Because of how Modo sets up the Python interpreter, be sure to set kEmbedded=1 in your copy of wingdbstub.py
  • In your code, where you initiate debugging, use the debugger API to ensure the debugger is connected to the IDE before any other code executes, as follows:
import wingdbstub
wingdbstub.Ensure()
  • In some cases you may need to edit wingdbstub.py to set WINGHOME to point to the directory where Wing is installed. This is usually set up automatically by Wing's installer, but won't be if you are using the .zip or .tar installation of Wing. Note that if you edit wingdbstub.py after Modo has already imported it then you will need to restart Modo to get it to import the modified wingdbstub.
  • Then click on the bug icon in the lower left of Wing's window and make sure that Accept Debug Connections is checked.

At this point, you should be able to reach breakpoints by causing the scripts to be invoked from Modo.

However, as of early 2024, running a script in Modo does not set up the file name in the compiled Python code correctly, so breakpoints only work in modules that are imported into your top-level script (the one that Modo imports and runs). This limitation is easily worked around by simply placing your code in another file and importing that file into the top-level script. For example, if the script Modo runs is myscript.py then you might put all your code in myscript_impl.py and change myscript.py to contain only import myscript_impl.

Once debugging starts, when a breakpoint or exception is reached, Wing should come to the front and show the place where the debugger stopped. Although the code is running inside Modo, editing and debugging happens inside Wing.

Reloading Code into Modo

By default you'll need to restart Modo before changes you have made to files imported by your scripts will be seen by Modo. This is a result of Python only being loaded once at startup in Modo, so previously executed imports will not be reloaded if the underlying code has changed.

Since you cannot stop at breakpoints in top-level Modo scripts (as noted above) this will affect most of your code and can get annoying.

A better way to approach this is to write a small utility dbgsupport.py with the following content:

import sys

def import_module(module_name):
    if module_name in sys.modules:
        del sys.modules[module_name]
    module = __import__(module_name)
    return module

Then you can replace import myscript_impl in your top-level Modo script with code like this:

from dbgsupport import import_module
myscript_impl = import_module('myscript_impl')

Now every time you run your script it will be using the latest version of the file myscript_impl.py from disk, even if you don't restart Modo.

There are some limitations to reloading modules like this. For example if other code holds onto references to functions, classes, methods, or other values in myscript_impl, then those will not be updated automatically as the module reloads. Also, if your code stores state somewhere outside of the module, then that will not be cleared or reloaded unless done explicitly by the new module import. In most cases, you won't run into these limitations but it's a good idea to be mindful about how resources in your reloaded modules are used.

Related Documents

For more information see: