Select to view content in your preferred language

Debugging a python script running in a toolbox

2574
8
08-11-2023 01:52 PM
DonaldPike
Occasional Contributor

I'm investigating the capabilities of running a python script through a toolbox. I have a very simple script that appears to complete successfully, but as I get into writing more complicated logic, I'm wondering what techniques there are for debugging python toolbox scripts? I tried putting in a print() statement but I'm not able to figure out where I can view that output (if anywhere). If print statements can't be used, what are other techniques that can be used to debug scripts?

Here's a screenshot of how I'm running a simple script and the code it contains:
Annotation-Annotation on 2023-08-11 at 13-39-11.png.png

Tags (1)
0 Kudos
8 Replies
DanPatterson
MVP Esteemed Contributor

You need to use AddMessage.

I use this function to cover tool and standalone scripts... just pass it a text `msg`

def tweet(msg):
    """Print a message for both arcpy and python."""
    m = "\n{}\n".format(msg)
    AddMessage(m)
    print(m)

... sort of retired...
JohannesLindner
MVP Alum

The tools don't use the Python Window console, you aren't able to see print() output. Instead, use arcpy.AddMessage():

# bla bla
arcpy.AddMessage("This is a debug message, all is well...")
# bla bla

 

The messages will be visible in the tool's details:

JohannesLindner_0-1691788046087.png

 


Have a great day!
Johannes
BlakeTerhune
MVP Regular Contributor

For debugging your main code block, use the arcpy message functions to write to the geoprocessing history output. For debugging code in updateMessages() when validating parameter inputs, I use the message methods on the parameter object to output debug info to the little tooltip messages that pop up on the tool interface in ArcGIS Pro. It looks like your toolbox doesn't have any parameters, so you might not need the parameter messaging.

Also keep in mind that when you make changes to the code of the toolbox, you need to restart ArcGIS Pro. There is a way around having to restart ArcGIS Pro, which you can find here:

Editing a Python toolbox—ArcGIS Pro | Documentation

Luke_Pinner
MVP Regular Contributor

As you get into more complicated scripts, one way is to do all your testing and debugging in a proper IDE such as PyCharm or Visual Studio Code.  Keep all the logic in functions (just as you've got in your screenshot) and then either

  • in the if __name__ == "__main__": block  comment out the arcpy.GetParameterAsText lines and replace with hardcoded values and run in the IDE debugger, or
  • leave your script as-is, create a test/debug script that imports your script and calls the function with hardcoded values and run the test/debug script in the IDE debugger. 
BlakeTerhune
MVP Regular Contributor

@Luke_Pinner wrote:

create a test/debug script that imports your script and calls the function with hardcoded values and run the test/debug script in the IDE debugger. 


Oh, that's an interesting idea. Could you share a sample of your calling script?

DavidSolari
MVP Regular Contributor

Here's one script structure you can use:

 

from __future__ import annotations
import arcpy


def main(param1: int, param2: str):
    return str(param1) + " " + param2    


def execute(params: list[Parameter], messages = None):
    param1 = params[0].value
    param2 = params[1].valueAsText
    params[2].value = main(param1, param2)


if __name__ == "__main__":
    execute(arcpy.GetParameterInfo())

 

This structure puts all the main program logic inside a "main" function that accepts standard Python types. If you run this through a standard toolbox (or bridge the call to execute from a Python toolbox) you extract the parameter values, pass them into "main" and set a derived parameter using the return value. However, you can import "main" from this file into a test file and call it with premade parameters and test the results. This makes it easier* to write unit tests for your script tools as well as launching the tool from outside of ArcGIS Pro which enables proper debugging. That said, you'll still need to AddMessage debug your parameter object related code if you don't have Visual Studio 2019 on hand.

*The actual hard part with writing script tool tests is wrangling the GIS data and making meaningful comparisons against "good" data but that's a story for another day

Luke_Pinner
MVP Regular Contributor

@BlakeTerhune wrote:
Oh, that's an interesting idea. Could you share a sample of your calling script?

Script tool (scripttool.py)

import arcpy

def main(parameter1, parameter2):
    #do something with parameters
    return

if __name__ == "__main__":
    #this won't get run when imported
    param1 = arcpy.GetParameterAsText(1)
    param2 = arcpy.GetParameterAsText(2)

    main(param1, param2)

Test script (test.py)

import scripttool

# Some hardcoded path for debugging
parameter1 = "D:/Temp/test2.shp" 
parameter2 = "D:/Temp/test2.shp" 

scripttool.main(parameter1, parameter2):

 

by Anonymous User
Not applicable

You can attach to the process via Visual Studio or PyCharm (both do validation and execution, VS also does debugging toolboxes).  esri provided a guide for it.

get-started/debugging-python-code