What is a Python toolbox

Python toolboxes are geoprocessing toolboxes that are created in Python. A Python toolbox and its tools look, act, and work the same way as other toolboxes and tools created in any other way. A Python toolbox is a Python file with a .pyt extension that defines a toolbox and one or more tools.

Once created, tools in a Python toolbox provide the following:

  • A script tool that you create is an integral part of geoprocessing in the same way as a system tool—you can open it from the Catalog pane, use it in ModelBuilder and the Python window, and call it from another script.
  • You can write messages to the Geoprocessing history window and tool dialog box.
  • Using built-in documentation tools, you can provide documentation.
  • When the script is run as a script tool, ArcPy is aware of the application it was called from. Settings made in the application, such as arcpy.env.overwriteOutput and arcpy.env.scratchWorkspace, are available from ArcPy in the script tool.

Create a Python toolbox

To create a Python toolbox, right-click the folder where you want to create the toolbox and click New > Python Toolbox.

Initially, the Python toolbox includes a Python class named Toolbox that defines characteristics of the toolbox and a Python class named Tool that provides a stubbed-out geoprocessing tool.

The following table shows the steps and links to information for creating a tool in a Python toolbox:

Get started

Python toolbox example

The example below is of a Python toolbox containing a single tool. The tool, named CalculateSinuosity, adds a field and calculates the sinuosity of the feature—the sinuosity being a measure of how a line bends.

Note:

To use this tool, copy the sample code into a Python integrated development environment (IDE), or Notepad, and save the file with a .pyt extension.

import arcpy

class Toolbox(object):
    def __init__(self):
        self.label =  "Sinuosity toolbox"
        self.alias  = "sinuosity"

        # List of tool classes associated with this toolbox
        self.tools = [CalculateSinuosity] 

class CalculateSinuosity(object):
    def __init__(self):
        self.label       = "Calculate Sinuosity"
        self.description = "Sinuosity measures the amount that a river " + \
                           "meanders within its valley, calculated by " + \
                           "dividing total stream length by valley length."

    def getParameterInfo(self):
        #Define parameter definitions

        # Input Features parameter
        in_features = arcpy.Parameter(
            displayName="Input Features",
            name="in_features",
            datatype="GPFeatureLayer",
            parameterType="Required",
            direction="Input")
        
        in_features.filter.list = ["Polyline"]

        # Sinuosity Field parameter
        sinuosity_field = arcpy.Parameter(
            displayName="Sinuosity Field",
            name="sinuosity_field",
            datatype="Field",
            parameterType="Optional",
            direction="Input")
        
        sinuosity_field.value = "sinuosity"
        
        # Derived Output Features parameter
        out_features = arcpy.Parameter(
            displayName="Output Features",
            name="out_features",
            datatype="GPFeatureLayer",
            parameterType="Derived",
            direction="Output")
        
        out_features.parameterDependencies = [in_features.name]
        out_features.schema.clone = True

        parameters = [in_features, sinuosity_field, out_features]
        
        return parameters

    def isLicensed(self):
        return True

    def updateParameters(self, parameters):
        if parameters[0].altered:
            parameters[1].value = arcpy.ValidateFieldName(parameters[1].value,
                                                          parameters[0].value)
        return

    def updateMessages(self, parameters):
        return

    def execute(self, parameters, messages):
        inFeatures  = parameters[0].valueAsText
        fieldName   = parameters[1].valueAsText
        
        if fieldName in ["#", "", None]:
            fieldName = "sinuosity"

        arcpy.management.AddField(inFeatures, fieldName, 'DOUBLE')

        expression = '''
import math
def getSinuosity(shape):
    length = shape.length
    d = math.sqrt((shape.firstPoint.X - shape.lastPoint.X) ** 2 +
                  (shape.firstPoint.Y - shape.lastPoint.Y) ** 2)
    return d/length
'''

        arcpy.management.CalculateField(inFeatures,
                                        fieldName,
                                        'getSinuosity(!shape!)',
                                        'PYTHON_9.3',
                                        expression)

    def postExecute(self, parameters):
        return

Related topics