Arcpy, Python, Tutorial

Tutorial: Arcpy basics

The following tutorial develops some basics for using the Arcpy library with Python.

If you are doing Python development, you may be interested in my Windows Dev Stack, which describes my development environment from high level technologies down to specific apps, and how they all work together.

1. Every script using Arc functions must start with import arcpy

import arcpy

2. Get user inputs with ‘GetParameterAsText’

import arcpy

# get input feature class
inputFeatureClass = arcpy.GetParameterAsText(0)

This gets the first user entered parameter as text. If you haven’t specified any parameters when adding to Arc (see step 3) it will cause the script to fail.

3. Using the tool in Arc

Right click on a toolbox you can edit (if you haven’t already, you will have to create one in “My Toolboxes” or within a folder), go down to ‘Add’ and select ‘Script…’, give it a name and label, select the script file, then add the parameters. For this example we are getting a Feature Class, so call it InputFeatureClass (or something meaningful) and set the Data Type to Feature Class. Click Finish. Double click on your new script tool to use it. At the moment it does nothing, but if you give it a feature class and click OK, it should run happily and say it was successful.

From now on we can just edit the script where it is and the changes will carry through, you won’t need to import it again.

It is important to note that paths to feature classes are just strings, e.g. ‘C:\\GISData\\NYC\\2007\\Networks.gdb\\BusRoutes’.

4. Adding messages to the display with ‘AddMessage’

import arcpy

# get input feature class
inputFeatureClass = arcpy.GetParameterAsText(0)

# inform user of selected feature class path
arcpy.AddMessage('  Input Feature Class: '+inputFeatureClass)

Save the script and run it again, and it will now print the feature class path before finishing.

5. Performing a geoprocessing operation

Let’s do a buffer on the input features, and also get the user to input the buffer size for the operation; you will need to right click on the tool in Arc, go down to Properties, and in the parameters tab add the parameter BufferSize_m as a Long (integer).

Buffer also requires an output feature class, so you will have to add that to the parameters as well; its data type should be feature class, but you will need to set the Direction (under Parameter Properties) to Output.

The script now becomes (with the message made a little more meaningful):

import arcpy

# get input feature class
inputFeatureClass = arcpy.GetParameterAsText(0)

# get buffer size
buffer = arcpy.GetParameterAsText(1)

# get output feature class
outputFeatureClass = arcpy.GetParameterAsText(2)

# inform user of selected feature class path
arcpy.AddMessage('  Buffering input Feature Class, '+inputFeatureClass+' by '+buffer+' Meters and writing to: '+outputFeatureClass)

buffer_corrected = buffer + ' Meters'

arcpy.Buffer_analysis(inputFeatureClass,  outputFeatureClass, buffer_corrected)

This should help you get started…

Other tips:

  1. do some Pyhton tutorials, and
  2. constantly refer to the documentation (either within Arc, or else on the ESRI website)

9 thoughts on “Tutorial: Arcpy basics

  1. Using ArcEditor 10.0, I am trying to resurrect the old script in Arc 9, which used to import textfile coords into a feature class using a script in ArcToolbox accessed from within ArcMap.

    I can import the script to a new Toolbox and run it from ArcCatalog in Arc 10, but the dialog box for the output feature class path/shapefilename is pre-populated with the path to Default.gdb in my user profile.

    What I want is for the featureclass dialog box to be pre-populated with the same path/filename as input/navigated to for the input text file, with of course the extension changed from .txt to .shp.

    The Python script is:-

    Tool Name: CreateFeaturesFromTextFile
    Source Name:
    Version: ArcGIS 9.1
    Author: Environmental Systems Research Institute Inc.
    Required Argumuments: An Input Text File containing feature coordinates
    An Input Character designating the decimal separator used in the text file.
    An output feature class
    Optional Arguments: A spatial reference can be specified. This will be the
    spatial reference of the output fc.
    Description: Reads a text file with feature coordinates and creates a feature class
    from the coordinates.

    import string, os, sys, locale, arcgisscripting
    gp = arcgisscripting.create()
    gp.overwriteoutput = 1

    msgErrorTooFewParams = “Not enough parameters provided.”
    msgUnknownDataType = ” is not a valid datatype. Datatype must be point, multipoint, polyline or polygon.”
    msgErrorCreatingPoint = “Error creating point %s on feature %s”

    # sets all the point properties
    def createPoint(point, geometry):
    try: = geometry[0]
    point.x = geometry[1]
    point.y = geometry[2]
    # When empty values are written out from pyWriteGeomToTextFile, they come as 1.#QNAN
    # Additionally, the user need not supply these values, so if they aren’t in the list don’t add them
    if len(geometry) > 3:
    if geometry[3].lower().find(“nan”) == -1: point.z = geometry[3]
    if len(geometry) > 4:
    if geometry[4].lower().find(“nan”) == -1: point.m = geometry[4]
    return point
    raise Exception, msgErrorCreatingPoint

    # get the provided parameters
    inputTxtFile = open(gp.getparameterastext(0))
    fileSepChar = “.”
    outputFC = gp.getparameterastext(1)
    # spatial reference is optional
    outputSR = gp.getparameterastext(2)

    # make sure the text type specified in the text file is valid.
    inDataType = inputTxtFile.readline().strip().lower()
    dataTypes = [“point”, “multipoint”, “polyline”, “polygon”]
    if inDataType.lower() not in dataTypes:
    msgUnknownDataType = “%s%s” % (inDataType, msgUnknownDataType)
    raise Exception, msgUnknownDataType

    # create the new featureclass
    gp.toolbox = “management”
    gp.CreateFeatureclass(os.path.split(outputFC)[0], os.path.split(outputFC)[1], inDataType, “#”, “ENABLED”, “ENABLED”, outputSR)
    # create a new field to assure the id of each feature is preserved.
    idfield = “File_ID”
    gp.addfield(outputFC, idfield, “LONG”)
    # get some information about the new featureclass for later use.
    outDesc = gp.describe(outputFC)
    shapefield = outDesc.ShapeFieldName
    # create the cursor and objects necessary for the geometry creation
    rows = gp.insertcursor(outputFC)
    pnt = gp.createobject(“point”)
    pntarray = gp.createobject(“Array”)
    partarray = gp.createobject(“Array”)

    locale.setlocale(locale.LC_ALL, ”)
    sepchar = locale.localeconv()[‘decimal_point’]

    # loop through the text file.
    featid = 0
    lineno = 1
    for line in inputTxtFile.readlines():
    lineno += 1
    # create an array from each line in the input text file
    values = line.replace(“\n”, “”).replace(“\r”, “”).replace(fileSepChar, sepchar).split(” “)

    # for a point feature class simply populate a point object and insert it.
    if inDataType == “point” and values[0].lower() != “end”:
    row = rows.newrow()
    pnt = createPoint(pnt, values)
    row.SetValue(shapefield, pnt)
    row.SetValue(idfield, int(values[0]))

    # for a multipoint the text file is organized a bit differently. Groups of points must be inserted at the same time.
    elif inDataType == “multipoint”:
    if len(values) > 2:
    pnt = createPoint(pnt, values)
    elif (len(values) == 2 and lineno != 2) or values[0].lower() == “end”:
    row = rows.newrow()
    row.SetValue(shapefield, pntarray)
    # store the feature id just in case there is an error. helps track down the offending line in the input text file.
    if values[0].lower() != “end”:
    row.SetValue(idfield, featid)
    featid = int(values[0])
    row.SetValue(idfield, featid)
    elif (len(values) == 2 and lineno == 2):
    featid = int(values[0])

    # for polygons and lines. polygons have a bit of logic for interior rings (donuts).
    # lines use the same logic as polygons (except for the interior rings)
    elif inDataType == “polygon” or inDataType == “polyline”:
    #takes care of
    #adds the point array to the part array and then part array to the feature
    if (len(values) == 2 and float(values[1]) == 0 and lineno != 2) or values[0].lower() == “end”:
    row = rows.newrow()
    row.SetValue(shapefield, partarray)
    # store the feature id just in case there is an error. helps track down the offending line in the input text file.
    if values[0].lower() != “end”:
    row.SetValue(idfield, featid)
    featid = int(values[0])
    row.SetValue(idfield, featid)
    #adds parts and/or interior rings to the part array
    elif (len(values) == 2 and float(values[1]) > 0) or values[0].lower() == “interiorring”:
    #add points to the point array
    elif len(values) > 2:
    pnt = createPoint(pnt, values)
    elif (len(values) == 2 and lineno == 2):
    featid = int(values[0])

    del rows
    del row

    except Exception, ErrorDesc:
    # handle the errors here. if the point creation fails, want to keep track of which point failed (easier to fix the
    # text file if we do)
    if ErrorDesc[0] == msgErrorCreatingPoint:
    if inDataType.lower() == “point”:
    msgErrorCreatingPoint = msgErrorCreatingPoint % (values[0], values[0])
    msgErrorCreatingPoint = msgErrorCreatingPoint % (values[0], featid)
    elif ErrorDesc[0] != “”:


    # make sure to close up the fileinput no matter what.
    if inputTxtFile: inputTxtFile.close()
    [end of Python script]

    Sorry to bother you with this, but ESRI help is useless and unless a Good Samaraton in an Arc Forum spots this I’m stuck,
    many thanks, Rob P

    1. Hi Rob,

      Your question iss, essentially, is it possible to define the default value for a parameter in an ArcToolbox script based upon one of the other parameters?

      As far as I know, no… The best you might be able to do is set the default to something a bit better than the default GDB (this can done by right clicking on the tool in ArcMap, going to parameters tab, clicking on the parameter in question and then in the bottom pane editing the Default variable).


      1. Stacy,

        Thanks for your response. Since posting on your site, I have solved the problem – by trial and error as I am a Python novice. The following is what I came up with:-

        I have now completed development of the Python code for this script. To bring the CreateFeatures tool up to Arc 10.0, such that your output shapefile has the same root filename as the input, proceed as follows:

        In the main script, change the fileseparator character line to

        fileSepChar = “.”

        This removes having to continually input the same character, as a separate parameter, each time you run the tool. If the decimal character is a comma in your region, change to that instead. In the lines where you run getparametersastext to input outputFC, outputSR, change the digits to 1,2 respectively (as we’ve removed the decimal character input).

        In the script tool Properties>Parameters, set the three parameter Data Types as Text File, String, and Spatial Reference respectively.

        In the script tool Properties>Validation, change the script to read as follows:

        class ToolValidator:
        “””Class for validating a tool’s parameter values and controlling
        the behavior of the tool’s dialog.”””

        def __init__(self):
        “””Setup arcpy and the list of tool parameters.”””
        import arcpy
        self.params = arcpy.GetParameterInfo()

        def initializeParameters(self):
        “””Refine the properties of a tool’s parameters. This method is
        called when the tool is opened.”””

        def updateParameters(self):
        “””Modify the values and properties of parameters before internal
        validation is performed. This method is called whenever a parmater
        has been changed.”””
        import string
        if self.params[0].value:
        if not self.params[1].value:
        inputTxt = str(self.params[0].value)
        outputTxt = str.replace(inputTxt,”txt”,”shp”)
        self.params[1].value = outputTxt


        def updateMessages(self):
        “””Modify the messages created by internal validation for each tool
        parameter. This method is called after internal validation.”””
        import os
        if self.params[1].altered:

        outputTxt = str(self.params[1].value)
        self.params[1].setWarningMessage(outputTxt + ” exists”)


        Save the updated Validator script and hit Apply, then OK. You should then be able to run the script to import ESRI-format text files into shapefile Feature classes. The behaviour of the tool as described will just give a warning over output shapefile name if such exists, but you can go ahead and optionally pick Spatial Ref for the feature class, click OK, and the shape with that name will be overwritten without further ado. Alternatively, change the output name to a new file – when you click in the Spatial Ref box the output warning message will disappear.

        Hopefully this will help anyone struggling to update this tool to 10.0, or in fact any of the old Samples toolset.

        Best Regards,
        Rob P

  2. Can you please include a tutorial about using arcpy to batch resource multiple data sources in multiple mxd’s? -Thank you.

  3. What would prevent arcpy.GetParameterAsText from not getting the specified table?

    >>> import arcpy, sys

    >>> fc = arcpy.GetParameterAsText(0)
    #the columns I want to change
    >>> total = “COUNT_BIN_STATE”
    >>> final = “COVERAGE”

    #nest a searchcursor within an updatecursor to effect the change

    >>> with arcpy.da.UpdateCursor(fc, (total, final,)) as cursor:
    ctotal = sum([row[0] for row in arcpy.da.SearchCursor(fc, (total, total,))])
    for rows in cursor:
    rows[1] = (rows[0]/float(ctotal))*100

    The problem is that the script does not even run into the UpdateCursor. I assume that fc was not instantiated by the tool. Can you assist me decipher this because I even tried your code to see if maybe I making a mistake, but to no avail. It seems like your code too does not populate the variables.

    1. I would suggest you use arcpy.AddMessage(fc) to see how the fc variable is coming through…

      On your second line I am unsure why you have the total field listed twice.

  4. Reblogged this on Polymathic Suman and commented:
    It’s a handy tool for Geographical Information Science (GIS) Analysts. I am revising and sharpening it. If you want, please start with the basics. Thank you for the post.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s