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:
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)
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:
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:
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
@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?
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
@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):
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.