Remote Debugging

I just thought I’d share my setup that I use for debugging Toolkit code. Note that I’m using the paid version of PyCharm in order to do this. I believe it should be possible with Visual Studio Code as well, and I may add details on that later if I can get it working.

Why use a debugger?

Using a debugger can be extremely useful, as you can do all sorts of things like

  • Add breakpoints in your code.
  • Pause and step through the live execution
  • Read variable values as you go.

If you’re running your code through an IDE, then you can usually make use of the IDE’s debugger, however, it’s not so easy to debug your code when you need to run it in a DCC such as Maya or Nuke. That’s where remote debugging can come in. Typically this is used when you want to debug code that is running on another computer, but we can also use it to debug code that is running in a different process.

Please note that this isn’t something that Shotgun directly supports, I’ve added it here as a hopefully useful suggestion.

Setting it up

How you approach remote debugging will depend entirely on what IDE you’re using, and some may not support it at all. You should check out your IDE’s documentation to find out what’s possible.

Two IDEs that do support remote debugging are PyCharm (professional edition only) and Visual Studio Code (Free). There may be others as well.

Here is an example of how to get this up and running with PyCharm.

  1. Make sure that you’re working in a sandbox configuration and that the code for the app, engine, or framework you want to debug is local to your machine.

  2. Set your Toolkit configuration to point to your local copy of the app/engine/framework, by modifying the location descriptor to become a path/dev descriptor.

  3. Open up the same app code in an existing project or as a new project in PyCharm.

  4. In PyCharm you can set up Python Remote Debug just like in their documentation, however, rather than pointing at a different machine, you can point at localhost.

  5. Now you can start up the debugger:

  6. Run the following code in your software to connect to the remote debugger. Note the path to the pydevd module maybe different on your machine:

    import sys sys.path.append("/Applications/PyCharm.app/Contents/debug-eggs/pydevd-pycharm.egg")
    import pydevd
    pydevd.settrace('localhost', port=1234, stdoutToServer=True, stderrToServer=True)
    

    The above code can either be inserted into your Hook or App, or you can run it separately in your software’s Python editor once it’s launched.

  7. Once you’ve run the above code, the Software will likely freeze until you resume from PyCharm. Now all that is left to do is to add your breakpoints to your code and start debugging.

16 Likes

Part 2 Visual Studio Code remote debugging

So I managed to get the Visual Studio Code remote debugging working as well on Windows.

I couldn’t get it to work on Mac, due to the fact that it refused to download a more recent version of the Python Extension than 2018.6.0 which has a bug that means it can’t connect. That might just be problem isolated to me, but be warned, first check your Python extension is up to date. I have also not tried Linux

So as I mentioned in my first post, you can get Visual Studio Code and set this up for free.

Setting it up

So I essentially followed these steps:

  1. Open the app folder in VS Code. It must be the folder, not just the individual python file you want to debug.

  2. Ensure the python extension is installed and uptodate:

  3. Now add the remote debug configuration.

    • The IP should be local host.
    • The port doesn’t matter too much as long as it doesn’t clash with a different process.
    • The localRoot and remoteRoot should be "${workspaceFolder}", unless Toolkit is running the code from a different location, then the folder you opened in VS Code.

  4. Download ptvsd. The easiest way I found of doing this, was to pip install it to my local python intepreter. But since we need to import it in something like Maya, which has its own python intepretter, I copied the ptvsd folder from the site-packages folder to a separate location. The reason I did this, is because it is never a good idea to sys.path.append the site-packages folder from a different interpreter, as some libraries might be compiled specifically for a given interpreter. Therefore you might see errors if Maya’s native Python interpreter libs clash with your system installed libs.

  5. Now you can either add the following code to your app, or run it in the Software’s native python script editor:

    import sys
    # Change the path to match where ever you copied the `ptvsd` package.
    sys.path.append("E:\\python_libs")
    import ptvsd
    
    # Allow other computers to attach to ptvsd at this IP address and port.
    ptvsd.enable_attach(address=('localhost', 5678), redirect_output=True)
    
    # Pause the program until a remote debugger is attached
    ptvsd.wait_for_attach()
    
  6. Start the debugger in VS Code:
    VS Code select and start debugger

Now it should stop at any breakpoints you’ve added in your code!
Happy bug hunting!

9 Likes

The “attach code” can be placed at top level in the module being debugged.

When the remote module being debugged runs, it will silently stop at wait_for_attach.

After that moment we need to press RUN twice, once to attach and again to continue the code to a breakpoint.

3 Likes

Thank you this works great. Got it working to debug python code running in RV with VS Code

This is indeed pretty cool!

I haven’t had the chance to try ptvsd yet. I work in emacs, and had success with remote_pdb and realgud. Should write this up at some point.

This is great! Any suggestions on how to enable / disable remote debugging on-demand in ShotGrid? Where can I put some code to do it instead of adding the ptvsd.enable_attach() call in arbitrary files?

@jrapczak I run attach cmd directly from within apps console once it gets started. No need to insert it to the code at all. Of course you have to do it again if the app is restarted.

For those who are wondering how to debug on Visual Studio Code today (2023), since ptvsd is now deprecated, the current tool to use is microsoft/debugpy: An implementation of the Debug Adapter Protocol for Python (github.com).

Instructions are pretty much the same. I can add in step 6 that instead copying the library from site-packages you can just:

pip install debugpy -t  C:\Users\myuser\Code\python-libs

Finally, step 7 can now be:

# installed debugpy with pip install -t to this directory
import sys; sys.path.append("C:/Users/myuser/Code/python-libs")

import debugpy
# required for hosted Python (e.g. Maya)
# got it from pyenv python >>> print(sys.executable)
debugpy.configure(python=r"C:\Users\myuser\.pyenv\pyenv-win\versions\3.9.13\python.exe")

try:
    debugpy.listen(("127.0.0.1", 5678))
except RuntimeError as e:
    if "Only one usage of each socket address" in str(e):
        pass
debugpy.wait_for_client()
debugpy.breakpoint()

The reason behind the try block is because once the debugger is attached to a running Maya process, the listen function will fail if it runs again. Wrapping it in a try can let vscode attach the debugger to the same Maya process and keep debugging.

Let me know if you find ways to improve this update. I’ll be happy to discuss.

8 Likes

Thanks, that’s very nice. I gotta figure out a way to integrate it in emacs.

One year later I come back with an improved version of debugpy usage for vscode. Make sure you have the Python extension updated.

import sys
sys.path.append("C:/path/to/python-libs")
import debugpy
if not debugpy.is_client_connected():
    debugpy.configure(python=r"C:\Program Files\Shotgun\Python3\python.exe")
    debugpy.listen(("127.0.0.1", 5678))
    debugpy.wait_for_client()

Then, just set an editor breakpoint (red dot) and that’s all!

3 Likes