Python Debugging In Maya And The Terminal

Learning how to debug your python application or scripts is an extremely useful tool for your toolset. In this post, we will cover the different ways in which we can do python debugging in Maya and in the terminal.

You make mistakes, we all do. From the best programmers on earth to the novice who loses half a day tracking down a rogue curly-brace ( we have all been there, admit it!), we all make mistakes. Part of becoming a proficient and effective Technical Director is to be able to find mistakes and problems as fast as you can.

Without learning how to use a debugger, your diagnostics toolset will be limited to print() statements which can easily get out of hand. I have met many TDs who do really amazing work, and still rely on good ol' print(). I did exactly the same for years until I found myself dealing with a very large code base which had tons of dependencies, message passing, database access, access layers, configurations, etc. Basically, a mid-size project.

I realized I was wasting too much time trying to figure out why the THING IS NOT WORKING! so I looking into debuggers for python. After a while of using different debuggers, this is what I found and I hope you find it useful.

It's my opinion that there are three levels of python debugging we can use. Each one has its strengths and weaknesses. so let's give each of them a quick look.

For those of you who rater follow a video instead, here is a video explaining this topic.

Level 1 - PDB

Python provides a module named PDB as part of its core package. This makes PDB the core of the python debugging experience and in my opinion something that everyone who works with python should learn. It's not fancy, but you know it is always there. So when you find yourself debugging some code at a machine which does not have all of your fancy IDE settings, you can still get things done the right way.

Using PDB is pretty straightforward, simply import the "pdb" package into the source file where you want to start the debugging session and then call set_trace() where you would like the execution of the application to stop.

from interface import implements

from node import Node
from interfaces.property import PropertyI

#import the PDB package for debugging.
import pdb

class PropertySet(Node, interface.implements(PropertyI)):
    '''
    Collections are used to represent geometry and geometry groups
    which will later be bound to geometry or properties
    '''

    def setProperty(self):
        '''
        Sets the propery of a piece of geometry or light based on 
        information found in the matx definition
        '''
        # Have the debugger stop right here.
        pdb.set_trace()
        # you could also do
        # import pdb; pdb.set_trace()
        # for convenience
        pass
    

If you open a terminal and run your python script, the execution should stop at the line with the set_trace() call. The terminal should display a prompt with the words (pdbon the left margin. To control the debugger you can use any of the commands listed below, which are accessible by typing "help" at the prompt.

pdb help command output

Personally, I only use a handful of commands and I'm sure with due time I will learn more about them, but for now, this table explains the most common commands

Comand Description
w Print information of where the program is in execution. Prints the last line processed by python.
n Next, execute the next line in the program
c Continue, continue the execution of the script until the next breakpoint or unitl the end of the script
pp VARIABLE Do a pretty print of the value stored in VARIABLE
q Quit, exit the debugger and the program

These 5 commands will allow you to find our what is going on much, much faster than using print statements.

PDB in Maya

This method of debugging is supported by Maya. It is a little bit clunky because Maya will display a dialog box with a very small text input field. This field behaves pretty much like the prompt at the terminal. As soon as you hit enter, the statement will be executed and printed in the Maya script editor output. It is a bit annoying, but for quick debugging, it tends to work.

Maya PDB input dialog

Level 2 - PUDB

If you want a more visual representation of what is happening in the execution, but you still only have access to the terminal as your editor, then you can always use the python package pudb. Pudb is a terminal application, which looks a lot like the DOS applications of yester-years. To operate the debugger you will need to remember some shortcuts, but having the ability to see the data change as you execute each line of code is really useful.

One downside to PUDB is that it is a library that you will need to install on your machine or project. Sometimes you might not have write access to the system's python home. If that is the case you can always create a quick virtual environment with virtual dev. Once the environment is created you can source it to activate the environment.

rcortes@myFolder| virtualenv env
rcortes@myFolder| source env/bin/activate
(env)rcortes@myFolder| 

Next, you will need to install pudb. The easiest way to do this is through pip.

pip install pudb

Now you are ready to use PUDB. Using PUDB is just as straightforward as using PDB, simply import the "pudb" package into the source file where you want to start the debugging session and then call set_trace() where you would like the execution of the application to stop.

from interface import implements

from node import Node
from interfaces.property import PropertyI

#import the PUDB package for debugging.
import pudb

class PropertySet(Node, interface.implements(PropertyI)):
    '''
    Collections are used to represent geometry and geometry groups
    which will later be bound to geometry or properties
    '''

    def setProperty(self):
        '''
        Sets the propery of a piece of geometry or light based on 
        information found in the matx definition
        '''
        # Have the debugger stop right here.
        pudb.set_trace()
        # you could also do
        # import pudb; pudb.set_trace()
        # for convenience
        pass
    

If you open a terminal and run your python script, the execution should stop at the line with the set_trace() call and you will see your terminal change to something like this:

The terminal becomes an application, remeniscent of a 1980s high tech thriller! but in its simplicity there is a lot of power. Your screen might look different since I changed the color scheme on my config a long time ago.

The panes of the debugger are clearly marked. The top left, and the biggest pane will be your source viewer, whatever is the current line being evaluaged will show here. To the right, on top you will have a list of all the variables available in the local and global scopes. As you continue the execution of your script, you will see this list get larger and the values change which is very useful. Below the variables, you will find the Stack window which displays where you are in the code and what operations have been invoked to get you there. 

Below the Stack, you will find a list of breakpoints. When you are in the debugger, you can create additional breakpoints by hitting the "b" key. PUDB will remember the breakproint next time the program is ran. These breakpoints are displayed in the breakpoints list. Finally, at the bottom right you will have a python console which you can use to type any python statement. The console will inherit the scope of where excution is currently halted. Very useful for trying things on the fly.

The help screen can be easily accessed by clicking the "?" key, wich displays this screen.

PUDB in Maya

Regrettably,  we cant really use PUDB with Maya since the embedded python interpreter does not have access to the terminal. Maybe there is a way to get this to work, but I did not feel it was a good use of my time to go down that rabbit hole. Instead, I just jump right ahead to level 3 debugging which much nicer than using a terminal application. Let's check it out.

Level 3 - Pydevd

Most of us who "python" on a daily basis, eventually get used to an IDE for development. PyCharm, Eclipse + PyDev (or LiClipse) and WingIDE, all provide a debugging GUI which is way, way beyond what PDB and PUDB can do. To take advantage of the GUI you can use pydevd which works like a charm. How does it work? Quite simply really.

There is a common interface that most debuggers use and most IDEs support a way to launch a "debugging server", which is just a communication port that gets open in your computer and which is waiting for a "handshake". When you run your python application from the terminal, if the debugging handshake is emitted, then the debug server starts receiving the data from the application. This data is then displayed in a sleek, easy to use interface. Pretty cool, huh?

Ok, how do we set this up? First, you will need to install pydev with pip.

(env)rudy@myFolder| pip install pydevd

Next, you need to start the debug server in your IDE. At the moment I am using LiClipse as my IDE so I start the debug server by going to Windows->Perspective->Open Perspective->Other and selecting Debug from the list. Once you are in the Debug perspective, you can start the debug server by going to Pydev->Start Debug Server. This will show a couple of entries in the Debug panel as seen below. This means that the debug server is listening for incoming connections.

Pydev debug server waiting for connections

Finally, you need insert import pydevd; pydevd.setrace() where you want the execution to stop and the debugging session to begin. Note, you might need to insert a reload(pydevd) if you terminate the debug server or the debug process. This will force the application to establish the communications with the debug server.

Once the connection has been established, the debug panel will change and show you the existing variables in the current scope of your script. You can then control the execution of your script by using the icons in the toolbar, the commands available through the main Run menu. For your convenience, I have attached a screenshot of the menu entries which show the available shortcuts.

Pydevd debug server connected

Available shortcuts for pydevd

Pydevd In Maya

One of the coolest things about using pydevd within your IDE, is that you will be able to connect to pretty much any python script in your system (or from another machine, as long as you use the right IP address and port). This makes it ideal for debugging python in Maya, Houdini, Blender or any other DCC tool that supports python.

Conclusion

This was just an introduction to how to setup development in python, which will allow you to become a much more efficient TD or developer. There is a lot more information on the interwebs about how to use the three mentioned debuggers. We encourage you to invest a little bit of time and learn more about debugging techniques, but for now, you are at least all set up to get started.

Thanks for reading, don't forget to subscribe to our youtube channel for up to date videos.

Cheers!