Skip to content

Instantly share code, notes, and snippets.

@MichaelAldrich
Last active September 16, 2019 18:28
Show Gist options
  • Save MichaelAldrich/cad49ab96affadad39aab7f4fd9df6e9 to your computer and use it in GitHub Desktop.
Save MichaelAldrich/cad49ab96affadad39aab7f4fd9df6e9 to your computer and use it in GitHub Desktop.

Remote Debugging in Maya via vscode

vscode's Debugging and Remote Debugging tools are pretty cool, and they make debugging code running in maya significantly faster. Reducing the number of maya reboots and sometimes removing the need for ridiculous I got here! print debugging.

launch.json

The configuration files for the remote debugger are set via <open_folder>\.vscode\launch.json

Here is an example of a remote debugging configuration.

{
    "name": "Python: Maya Magic",
    "type": "python",
    "request": "attach",
    "port": 3000,
    "host": "localhost",
    "pathMappings": [
        {
            "localRoot": "${workspaceFolder}",
            "remoteRoot": "."
        }
    ]
}

The port is arbitrary, but should be noted. In this example 3000.

The host is localhost for remotely attaching to your local maya session, but can be set to the ip addresses of computers in your local network to debug over the network.

It's important that the "localRoot" of your configuration match the path that the python package was imported from, or else vscode will not stop at your editor breakpoints or provide auto-completion in the interactive console. I do not have clarity, but it's possible that your "localRoot" can match only the structure, even if it doesn't match the path directly, though I have not confirmed this.

ptvsd

To use the remote debugging tools, the ptvsd python package must be available in the python environment you wish to debug.

This is the necessary code to have a python session available for remote debugging.

import ptvsd
ptvsd.enable_attach(address=('0.0.0.0', 3000), redirect_output=True)

The important parameter to note in the above function is the port, in this example 3000.

The documentation for ptvsd provides a few other ways to make a session available.

debugging

Once your launch.json exists and you've run the relevant ptvsd code in your python session, you can launch the debug session from vscode, and it should stop at your breakpoints, allow stepping through and into your code as it runs, as well as providing an interactive python session to quickly and easily explore the current scope.

It's important to be aware that once a debug session has been attached to, performance is lost. In my benchmarks I saw speed drop to about 50% of the pre-attach speed. Usually this is a worthwhile tradeoff for the debugging speed you get in exchange.

extra fun

I do some extra setup to my userSetup.py and in a shelf button in order to make all of my maya sessions available for debugging, as well as allow myself to quickly cycle between available sessions without tedious lookup.

No reason this couldn't be dropped into a "debug" launch configuration for a standalone python tool, just would need some way to select a session, replacing the role of the shelf button.

userSetup.py

import ptvsd
def enable_debug_attach_on_valid_address():
    starting_port = 2999
    max_attempts = 30 # I dont't think I'll ever want more than 30 debug sessions.
    def attempt_port(test_port):
        try:
            ptvsd.enable_attach(address=('0.0.0.0', str(test_port)), redirect_output=True)
            return True
        except:
            print('Failed to enable debug at port ' + str(port))
            return False
    for port in range(starting_port, starting_port+max_attempts):
        if attempt_port(port):
            break
    else:
        return None
    return port
REMOTE_DEBUG_PORT = enable_debug_attach_on_valid_address()

I don't have any evidence there is value in starting at 2999 for port, it just became my default.

My intent is for this to fail gracefully, so it doesn't get in the way of an urgent maya launch. There is most likely more safety measures I could put it place, but so far this has been good.

shelf button

import json
import os

def activate_session_for_debug(port):
    config_path = os.path.expanduser('~/Projects/sandbox/.vscode/launch.json')
    config_name = "Python: Maya Magic"

    with open(config_path, 'r') as file_stream:
        launch_config = json.load(file_stream)
    configs = launch_config.get('configurations')
    for config in configs:
        if config.get('name') == config_name:
            config['port'] = port

    with open(config_path, 'w') as file_stream:
        json.dump(launch_config, file_stream, indent=4, separators=(',', ': '))
    return True

if not REMOTE_DEBUG_PORT:
    print('Session not available for debugging.')
elif activate_session_for_debug(REMOTE_DEBUG_PORT):
    print('Maya Magic debug port set to: ' + str(REMOTE_DEBUG_PORT))
else:
    print('Failed to set Maya Magic debug port.')

With this code in a shelf button, when the button is pressed, the "Maya Magic" debug configuration will be modified to connect to the maya sesion you pressed the shelf button in.

important notes
  • You must customize config_path to match your launch.json

  • It is critical that your config_name match the one in set in your launch.json

  • The default launch.json comes with some comments prefixed with // at the top that must be removed for it to be loaded via json.load

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment