[GIS] Debugging Python script tools of ArcPy

arcgis-10.2arcpypython-script-tool

I recently got an script tool in a tbx file to play with.

I'd like to see how the tool runs in a debugger to get a better idea of how it works. I've tried several paths to this, but all of them seem to have failed:

  1. Open in visual studio, or some other IDE: the windows explorer, of course, does not recognize .tbx as a container, and just displays garbage.
  2. Right click the tool and use the "Debug" option: tool runs as usual, but I have no control over stepping, breakpoints, etc. I can't see the code as it is running.
  3. Right click the tool and use the "Edit" button: python script opens in NotePad. There doesn't seem to be a way to choose another editor. Of course, notepad doesn't have a build or compile option, so I can't modify the code even to print output.
  4. Copying the code into Visual Studio and running it there: when trying to run debug from ArcMap, I run into this issue

Best Answer

To debug Python toolboxes I usually have a separate "debug.py" file in my project where I test just certain modules or code snippets. The script is very simple, set up like this:

import os
import arcpy

def main():
    # code to test here, set break point and step thru

if __name__ == "__main__":
    main()

When a Python toolbox throws an error, I inspect the line number and copy the function or method that contains the line in question into debug.py. I hard code the various input parameter values that the tool would normally have, and step thru my code and find exactly what the error is. Finally, I apply the changes to the Python toolbox .pyt file. I am currently using Visual Studio code to run my Python scripts.

edit:

I want to add this link as well: How to Debug Python Toolboxes in 3 Easy Steps. This article shows another easy method of debugging a python toolbox simply by adding a main() method:

class MyToolbox(object):
    def __init__(self):

class MyTool(object):
    def __init__(self):
        self.label = 'Tool 1'

def getParameterInfo(self):
    # parameters..
    return params

def execute(self, parameters, messages):
    # do stuff..
    return

def main():
    # set break point here, step thru
    tbx = MyToolbox()
    tool = MyTool()
    tool.execute(tool.getParameterInfo(), None)

if __name__ == "__main__":
    main()
Related Question