ArcGIS Pro Python toolbox
1 Custom toolbox vs. Python toolbox
Custom toolbox
- Organized in three parts
- Wizard for beginners
- Source code in any editor
- Parameters through the wizard
- Validation code through the toolbox
- Supports Python and model tools
Python toolbox
- Single Python script with a .pyt extension
- One class for the toolbox
- One class for each tool
- Source code in any editor
- Additional capabilities
- Value tables
- Composite data types
- Custom license checking
2 Hello World in custom toolbox
param1 = arcpy.GetParameterAsText(0)
param2 = sys.argv[2]
arcpy.AddError(param1)
arcpy.AddWarning(param2)
arcpy.AddMessage("Hello World!")
2.1 Try Hello World!
From ArcGIS Pro
From the command line (cmd.exe
) “after” closing ArcGIS Pro
"C:\Program Files\ArcGIS\Pro\bin\Python\Scripts\propy.bat" HelloWorld.py
3 Hello World in Python toolbox
HelloWorldPython.pyt
import arcpy
class Toolbox(object):
def __init__(self):
'''Define the toolbox (the name of the toolbox is the name of the
.pyt file).'''
self.label = 'HelloWorld Python Toolbox'
self.alias = 'HelloWorldPythonToolbox'
# List of tool classes associated with this toolbox
self.tools = [HelloWorldPython]
class HelloWorldPython(object):
def __init__(self):
'''Define the tool (tool name is the name of the class).'''
self.label = 'Hello World Python'
self.description = 'This is Hello World Python!'
self.canRunInBackground = False
def getParameterInfo(self):
'''Define parameter definitions'''
param1 = arcpy.Parameter(
displayName='Param 1',
name='param1',
datatype='GPString',
parameterType='Required',
direction='Input')
param2 = arcpy.Parameter(
displayName='Param 2',
name='param2',
datatype='GPString',
parameterType='Required',
direction='Input')
params = [param1, param2]
return params
def isLicensed(self):
'''Set whether tool is licensed to execute.'''
return True
def updateParameters(self, parameters):
'''Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parameter
has been changed.'''
return
def updateMessages(self, parameters):
'''Modify the messages created by internal validation for each tool
parameter. This method is called after internal validation.'''
return
def execute(self, parameters, messages):
'''The source code of the tool.'''
arcpy.AddError(parameters[0].valueAsText)
arcpy.AddWarning(parameters[1].valueAsText)
arcpy.AddMessage('Hello World Python!')
print('Done!')
return
3.1 Try Hello World Python!
From ArcGIS Pro
From the command line (cmd.exe
) “after” closing ArcGIS Pro
doit.py
import arcpy
arcpy.ImportToolbox('HelloWorldPython.pyt')
arcpy.HelloWorldPython_HelloWorldPythonToolbox('Hello', 'World')
Run
"C:\Program Files\ArcGIS\Pro\bin\Python\Scripts\propy.bat" doit.py
3.2 Need two files for testing?
Let’s try this.
MyModule.py
class MyPrint:
def __init__(self, name):
self.name = name
def print(self):
print(self.name)
printme.py
from MyModule import MyPrint
myprint = MyPrint('print me')
myprint.print()
3.3 Combine MyModule.py
and printme.py
Class and test code in one file
MyModule.py
class MyPrint:
def __init__(self, name):
self.name = name
def print(self):
print(self.name)
test = MyPrint('print myself')
test.print()
Good? Let’s use this module from printme.py
.
from MyModule import MyPrint
myprint = MyPrint('print me')
myprint.print()
What happens?
3.4 Proper way of combining MyModule.py
and printme.py
New MyModule.py
class MyPrint:
def __init__(self, name):
self.name = name
def print(self):
print(self.name)
if __name__ == '__main__':
test = MyPrint('print myself')
test.print()
Now, try the same printme.py
3.5 Can we use this pattern for Python toolboxes?
Try this HelloWorldPython.pyt
.
# Python toolbox code above
if __name__ == '__main__':
arcpy.ImportToolbox('HelloWorldPython.pyt')
arcpy.HelloWorldPython_HelloWorldPythonToolbox('Hello', 'World')
Run it.
"C:\Program Files\ArcGIS\Pro\bin\Python\Scripts\propy.bat" HelloWorldPython.pyt
What happens?
3.6 Separation of concerns
Design principal in software development
Separate presentation and logic layers.
What can we use when __name__
is always __main__
?
sys.executable
- From ArcGIS Pro:
C:\Program Files\ArcGIS\Pro\bin\ArcGISPro.exe
- From the command line:
C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\python.exe
Try this.
# Python toolbox code above
if not 'ArcGISPro.exe' in sys.executable:
arcpy.ImportToolbox('HelloWorldPython.pyt')
arcpy.HelloWorldPython_HelloWorldPythonToolbox('Hello', 'World')
What happens?
3.7 Proper way of testing Python toolboxes
Again, separation of concerns
We don’t want to emulate ArcGIS Pro just to pass the parameters
array with the valueAsText
attribute.
The execute
method is ArcGIS Pro’s interface to your algorithm.
Separate out your algorithm from execute
so you can invoke the algorithm without ArcGIS Pro.
Let’s try this.
# Python toolbox code here, but modify execute
def execute(self, parameters, messages):
'''The source code of the tool.'''
self.main(parameters[0].valueAsText, parameters[1].valueAsText)
return
def main(self, param1, param2):
arcpy.AddError(param1)
arcpy.AddWarning(param2)
arcpy.AddMessage('Hello World Python!..')
print('Done!')
return
if not 'ArcGISPro.exe' in sys.executable:
hello = HelloWorldPython()
hello.main('Hello', 'World')