Tutorial: Arcpy basics

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

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

'''script.py
'''
import arcpy

2. Get user inputs with ‘GetParameterAsText’

'''script.py
'''
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’

'''script.py
'''
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 happily.

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):

'''script.py
'''
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 in Arc, or on the ESRI website)
About these ads

, , , ,

  1. #1 by vadivelan on August 31, 2011 - 3:35 am

    Good one.. pls. write more..

    • #2 by StacyR on August 31, 2011 - 9:22 pm

      What would you like to know more about?

  2. #3 by Rob Pearce on January 14, 2012 - 4:41 am

    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: CreateFeaturesFromTextFile.py
    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:
    point.id = 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
    except:
    raise Exception, msgErrorCreatingPoint

    try:
    # 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]))
    rows.insertrow(row)

    # 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)
    pntarray.add(pnt)
    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])
    else:
    row.SetValue(idfield, featid)
    rows.insertrow(row)
    pntarray.removeall()
    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”:
    partarray.add(pntarray)
    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])
    else:
    row.SetValue(idfield, featid)
    rows.insertrow(row)
    partarray.removeall()
    pntarray.removeall()
    #adds parts and/or interior rings to the part array
    elif (len(values) == 2 and float(values[1]) > 0) or values[0].lower() == “interiorring”:
    partarray.add(pntarray)
    pntarray.removeall()
    #add points to the point array
    elif len(values) > 2:
    pnt = createPoint(pnt, values)
    pntarray.add(pnt)
    elif (len(values) == 2 and lineno == 2):
    featid = int(values[0])

    inputTxtFile.close()
    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])
    else:
    msgErrorCreatingPoint = msgErrorCreatingPoint % (values[0], featid)
    gp.AddError(msgErrorCreatingPoint)
    elif ErrorDesc[0] != “”:
    gp.AddError(str(ErrorDesc))

    gp.AddError(gp.getmessages(2))

    # 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

    • #4 by StacyR on February 2, 2012 - 9:31 am

      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).

      Regards,
      Stacy

      • #5 by Rob Pearce on February 2, 2012 - 10:25 pm

        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.”””
        return

        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

        return

        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:
        self.params[1].clearMessage()

        try:
        outputTxt = str(self.params[1].value)
        open(outputTxt)
        self.params[1].setWarningMessage(outputTxt + ” exists”)
        except:
        self.params[1].clearMessage()

        return

        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

  3. #6 by Allison on December 28, 2012 - 5:30 am

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

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 50 other followers

%d bloggers like this: