What is Python?
Transcription
What is Python?
What is Python? Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python Python is a free, cross-platform, open-source programming language that is both powerful and easy to learn. It is widely used and supported. To learn more about Python, visit python.org. Python was introduced to the ArcGIS community at 9.0. Since then, it has been accepted as the scripting language of choice for geoprocessing users and continues to grow. Each release has furthered the Python experience, providing you with more capabilities and a richer, more Python-friendly experience. ESRI has fully embraced Python for ArcGIS and sees Python as the language that fulfills the needs of our user community. Here are just some of the advantages of Python: Easy to learn and excellent for beginners, yet superb for experts Highly scalable, suitable for large projects or small one-off programs known as scripts Portable, cross-platform Embeddable (making ArcGIS scriptable) Stable and mature A large user community Python extends across ArcGIS and becomes the language for data analysis, data conversion, data management, and map automation, helping increase productivity. Learning Python The information contained here is not a Python language reference. Certain Python syntax and behavior are explained with respect to examples and concepts used to demonstrate how to write a geoprocessing script. A suitable Python reference book is strongly recommended to augment the information you find here. For Python beginners, Learning Python by Mark Lutz and David Ascher, published by O’Reilly & Associates, and Core Python Programming by Wesley J. Chun, published by Prentice Hall, are both good introductions to the language and are not overwhelming in scope. There are many other books on Python and its particular uses, with new ones being released regularly, so explore what is available. The Python Web site has full documentation for Python, but it is concise and developer oriented. There is a large online Python community with many online resources that are accessible from the Python home page. Python tutorials If you're new to Python, the external tutorials listed here are recommended for you. Python Tutorial is part of Python's own documentation. Python for Non-Programmers provides tutorials for those with limited programming experience. Python Language Reference describes the syntax and semantics of Python. Python tutorials for programmers The external tutorials listed here are aimed at those who have previous experience with other programming languages (Perl, Visual Basic, C). Python Tutorial is part of Python's own documentation. Python for Programmers provides tutorials for those with experience in other programming languages. Related Topics A quick tour of Python Essential Python vocabulary What is ArcPy? What is the Python window? Essential Python vocabulary Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python This document introduces some vocabulary that is essential to understanding the Geoprocessing with Python help. Term Description Python Python is an open-source programming language that was conceived in the late 1980s by Guido van Rossum, and introduced in 1991. It was first incorporated with ArcGIS 9.0 and has since become the preferred choice for users creating geoprocessing workflows. Python is supported by a growing and varied user community and provides easy readability, clean syntax, dynamic typing, and an extensive collection of standard and third-party libraries. PythonWin PythonWin is a widely used third-party Windows interface for Python and is available for installation on the ArcGIS installation media. ArcPy ArcGIS 10 introduces ArcPy (often referred to as the ArcPy site-package), which provides Python access for all geoprocessing tools, including extensions, as well as a wide variety of useful functions and classes for working with and interrogating GIS data. A site-package is Python's term for a library that adds additional functions to Python. Using Python and ArcPy, you can develop an infinite number of useful programs that operate on geographic data. ArcPy A module is a python file that generally includes functions and classes. ArcPy is modules supported by a series of modules, including a mapping module (arcpy.mapping), a Spatial Analyst module (arcpy.sa), and a Geostatistical Analyst module (arcpy.ga). ArcPy classes A class is analogous to an architectural blueprint. The blueprint provides the framework for how to create something. Classes can be used to create objects, often referred to as an instance. ArcPy classes, such as the SpatialReference and Extent classes, are often used as shortcuts to complete geoprocessing tool parameters that would otherwise have a more complicated string equivalent. ArcPy A function is a defined bit of functionality that does a specific task and can be functions incorporated into a larger program. In ArcPy all geoprocessing tools are provided as functions, but not all functions are geoprocessing tools. In addition to tools, ArcPy provides a number of functions to better support geoprocessing Python workflows. Functions or methods can be used to list certain datasets, retrieve a dataset's properties, validate a table name before adding it to a geodatabase, or perform many other useful scripting tasks. Stand-alone A Python script is a .py file that can be executed. A stand-alone Python script is a Python script .py file that can be executed from the operating system prompt or a development application like PythonWin or by double-clicking the .py in a Windows Explorer. Python script A Python script tool is a Python script that has been added to a geoprocessing tool toolbox. Once added as a script tool, the script tool becomes like any other geoprocessing tool—it can be opened and executed from the tool dialog box, used in the Python window and ModelBuilder, and called from other scripts and script tools. Python ArcGIS 10 introduces a new embedded Python experience. The geoprocessing window command line from past releases has been re-invented as a fully interactive Python window. This is a quick and convenient place to use Python from within ArcGIS to interactively run geoprocessing tools and functionality as well as take advantage of other Python modules and libraries. This window also provides a gateway for users to learn Python. The Python window can be used to execute a single line of Python code, with the resulting messages printed to the window. It is a useful place to experiment with syntax and work with short lengths of code and provides an opportunity to test your ideas outside a larger script. A quick tour of Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python Python is an open-source, general-purpose programming language used as a scripting language in ArcGIS geoprocessing. Geoprocessing functionality is accessible through Python using ArcGIS software's ArcPy site-package. ArcPy provides access to geoprocessing tools as well as additional functions, classes, and modules that allow you to create simple or complex workflows quickly and easily. ArcGIS applications and scripts written using ArcPy benefit from being able to access and work with the numerous Python modules developed by GIS professionals and programmers from many different disciplines. The additional power of using ArcPy within Python is the fact that Python is a generalpurpose programming language that is easy to learn and use. It is interpreted and dynamically typed, which provides you with the ability to quickly prototype and test scripts in an interactive environment while still being powerful enough to support the writing of large applications. Broadly speaking, ArcPy is organized in tools, environments, functions, classes, and modules. Running a tool This next example shows how to execute the Buffer tool. As the tool executes, the messages will appear by default on the right side of the Python window in the help section. >>> arcpy.Buffer_analysis("c:/data/Portland.gdb/streets", "c:/data/Portland.gdb/steets_buffer", "500 METERS") Here is another example of running tools. This example uses tools in the data management and conversion toolboxes. A field is added to the input streets feature class, the field is calculated, and the feature class is then loaded into an ArcSDE enterprise geodatabase. >>> import arcpy >>> arcpy.AddField_management("c:/data/Portland.gdb/streets", "LENGTH_MILES", "TEXT") >>> arcpy.CalculateField_management("c:/data/Portland.gdb/streets", "LENGTH_MILES", "!shape.length@miles!", "PYTHON_9.3") >>> arcpy.FeatureClassToFeatureClass_conversion("c:/data/Portland.gdb/streets", "Database Connections/MySDE.sde/PortlandDataset", "streets") Learn more about using tools in Python Getting results from a tool When a geoprocessing tool is executed, the results of the tool are returned in a result object. Typically, this object is the path to the output dataset produced or updated by the tool. In other cases, it may contain other value types, such as a number or Boolean. If an output for a tool is a multivalue parameter, the values can be returned as a list within a list. The following code examples show how return values are captured and what their values could be: Return the path of the output feature class. The result can be used as input to another function. >>> result = arcpy.Buffer_analysis("rivers", "riverBuf", "50 METERS") >>> print result C:\Portland\Portland_OR.gdb\riverBuf >>> arcpy.Clip_analysis("streets", result, "streets_50m_of_rivers") Return the number of features. >>> result = arcpy.GetCount_management("streets_50m_of_rivers") >>> print result.getOutput(0) 54 Return a list of default spatial grid indexes for a feature class. >>> result = arcpy.CalculateDefaultGridIndex_management("streets_50m_of_rivers") >>> for i in range(0, result.outputCount): ... print result.getOutput(i) ... 560 200 0 Using environment settings Geoprocessing environment settings can be thought of as additional parameters that affect a tool's results. They differ from normal tool parameters in that they are set separately from the tool and are interrogated and used by tools when they are run. Environment settings such as an area of interest, the coordinate system of the output dataset, and the cell size of a new raster dataset can all be specified and honored by the tools. Environment settings are available from the env class as properties. These properties can be used to retrieve the current environment values and set them. Below are examples of how to use environment values: Set the workspace environment. >>> arcpy.env.workspace = "c:/data/Portland.gdb" >>> arcpy.Buffer_analysis("streets", "streetBuf", "500 METERS") Set the spatial grid index to the return value of a tool. >>> arcpy.env.spatialGrid1 = arcpy.CalculateDefaultSpatialGridIndex_management("streets").getOutput(0) Get the current raster cell size setting and make sure it is a specific size for standard output. if arcpy.env.cellSize != 30: arcpy.env.cellSize = 30 Learn more about using environment settings in Python Using functions A function is a defined bit of functionality that does a specific task and can be incorporated into a larger program. In addition to tools, ArcPy exposes a number of functions to better support geoprocessing workflows. Functions can be used to list certain datasets, retrieve a dataset's properties, check for existence of data, validate a table name before adding it to a geodatabase, or perform many other useful scripting tasks. The example code below shows getting the properties of data and checking out an extension: import arcpy # prints True print arcpy.Exists("c:/data/Portland.gdb/streets") # prints NAD_1983_StatePlane_Oregon_North_FIPS_3601_Feet sr = arcpy.Describe("c:/data/Portland.gdb/streets").spatialReference print sr.name # prints Available print arcpy.CheckExtension("spatial") arcpy.CheckOutExtension("spatial") Learn more about using functions in Python Using classes ArcPy classes, such as the SpatialReference and Extent classes, are often used as shortcuts to complete geoprocessing tool parameters that would otherwise have a more complicated string equivalent. A class is analogous to an architectural blueprint. The blueprint provides the framework for how to create something. Classes can be used to create objects; this is often referred to as an instance. import arcpy prjFile = "c:/projections/North America Equidistant Conic.prj" spatialRef = arcpy.SpatialReference(prjFile) Learn more about using classes in Python Working with modules ArcPy includes modules covering other areas of ArcGIS. ArcPy is supported by a series of modules, including a mapping module (arcpy.mapping), a Spatial Analyst module (arcpy.sa), and a Geostatistical Analyst module (arcpy.ga). For example, the tools of the arcpy.sa module use tools in the Spatial Analyst toolbox but are configured to support Map Algebra. Thus, executing arcpy.sa.Slope is the same as executing the Slope tool from the Spatial Analyst toolbox. Related Topics Essential Python vocabulary What is Python? Copyright © 1995-2011 Esri. All rights reserved. 6/16/2011 Importing ArcPy Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools ArcGIS 10 introduces ArcPy, a Python site package that encompasses and further enhances the arcgisscripting module introduced at ArcGIS 9.2. ArcPy provides a rich and dynamic environment for developing Python scripts while offering code completion and integrated documentation for each function, module, and class. ArcGIS applications and scripts written using ArcPy benefit from being able to access and work with the numerous Python modules developed by GIS professionals and programmers from many different disciplines. The additional power of using ArcPy within Python is the fact that Python is a general purpose programming language that is easy to learn and use. It is interpreted and dynamically typed, which provides you with the ability to quickly prototype and test scripts in an interactive environment while still being powerful enough to support the writing of large applications. # Importing arcpy # import arcpy # Set the workspace environment and run Clip_analysis arcpy.env.workspace = "C:/Data/Tongass" arcpy.Clip_analysis("standb4", "clipcov", "standby_clip", "1.25") Once you have imported ArcPy, you can run all geoprocessing tools found in the standard toolboxes installed with ArcGIS: Analysis toolboxCartography toolboxConversion toolboxData Management toolboxEditing toolboxGeocoding toolboxLinear Referencing toolboxMultidimension toolboxSpatial Statistics toolbox Importing modules A module is a python file that generally includes functions and classes. ArcPy is supported by a series of modules, including a mapping module (arcpy.mapping), a Spatial Analyst module (arcpy.sa), and a Geostatistical Analyst module (arcpy.ga). To import an entire module, use the import module: # Import all of arcpy # import arcpy.mapping Of course, Python has many other core and third-party modules. If you wanted to also work with Python's core os and sys modules, you might use a similar import: # Import arcpy, os and sys # import arcpy import os import sys In many cases, you might not plan or need to use the entire module. One way to import only a portion of a module is to use a from-import statement. The below example imports the env class (the env class contains all the geoprocessing environments). Now instead of having to access environments as arcpy.env, you can simplify it as env. # Import env from arcpy and set the workspace environment # from arcpy import env env.workspace = "c:/data" Following the same thought process, sometimes you might want to draw attention to what a module or part of a module is identified as to make your script more readable, or perhaps the default name is just too long for your preferences. In any of these cases, you can use the form from-import-as. Like the previous example, the below example also imports the env class but assigns it the name ENV: # Import env from arcpy as ENV and set the workspace environment # from arcpy import env as ENV ENV.workspace = "c:/data" You could import the mapping module in the same fashion: # Import the mapping module from arcpy as MAP and create a MapDocument # object # from arcpy import mapping as MAP mxd = MAP.MapDocument("C:/maps/basemap.mxd") Another version of importing is the form from-import-*. The contents of the module are imported directly into the namespace, meaning you can then use all those contents directly without needing to prefix them. For example: # Import management from arcpy as * # from arcpy.management import * However, there are some risks associated with this approach. Other objects, variables, modules, and so forth, with the same name will be overwritten, not to mention that with large modules, your namespace can become particularly crowded and busy. Think about it this way: In the following example, both the management and analysis module are being imported as *. Both of these modules have a Clip tool. If you now try to use Clip, which Clip are you actually using? The answer is the second one, but this approach can lead to uncertainty and difficulty in reading the script. # Import the management and analysis modules from arcpy as * # from arcpy.management import * from arcpy.analysis import * # Which Clip is it? # Clip("standb4", "clipcov", "standby_clip", "1.25") However, in some cases, from-import-* can simplify your code, as in the case of the ArcGIS Spatial Analyst extension's sa module. One of the benefits of the sa module is that you can nest multiple classes and functions in a single line to produce an output raster object. License: Both of the following samples require the Spatial Analyst extension to run. # Import arcpy and the sa module as * # import arcpy from arcpy.sa import * arcpy.CheckOutExtension("spatial") # Get input # inRaster1 = inRaster2 = inRaster3 = parameters arcpy.GetParameterAsText(0) arcpy.GetParameterAsText(1) arcpy.GetParameterAsText(2) outRaster = (Raster(inRaster1) + (Raster(inRaster2) - Raster(inRaster3))) Now compare the next code block, which uses the conventional import-from statement. Now imagine adding a few more classes and functions into the code—the simple addition of sa. for every function and class adds up quickly, disrupting the readability and adding more bulk to the line. # Import arcpy and the sa module # import arcpy from arcpy import sa arcpy.CheckOutExtension("spatial") # Get input # inRaster1 = inRaster2 = inRaster3 = parameters arcpy.GetParameterAsText(0) arcpy.GetParameterAsText(1) arcpy.GetParameterAsText(2) outRaster = (sa.Raster(inRaster1) + (sa.Raster(inRaster2) sa.Raster(inRaster3))) Paths and import When using an import statement, Python looks for a module matching that name in the following locations (and in the following order): 1. Paths specified in the PYTHONPATH system environment variable 2. A set of standard Python folders (the current folder, c:\python2x\lib, c:\python2x\Lib\site-packages, and so on) 3. Paths specified inside any .pth file found in 1 and 2 For more information on this, see the following: http://docs.python.org/install/index.html#modifying-python-s-search-path. The installation of ArcGIS 10.0 products will install Python 2.6 if it isn't already installed. The installation will also add the file Desktop10.pth (or Engine10.pth or Server10.pth) into python26\Lib\site-packages. The contents of this file are two lines containing the path to your system's ArcGIS installation's arcpy and bin folders. These two paths are required to import ArcPy successfully in Python version 2.6. When using an import statement, Python refers to your system's PYTHONPATH environment variable to locate module files. This variable is set to a list of directories. Tip: If importing ArcPy produces either of the following errors, the required modules could not be found: ImportError: No module named arcpy ImportError: No module named arcgisscripting To address this, browse using Windows Explorer to the python26\Lib\site-packages folder and add or edit the Desktop10.pth file. The file should contain the two lines shown below (corrected to your system's path if they do not match): c:\Program Files\ArcGIS\Desktop10.0\arcpy c:\Program Files\ArcGIS\Desktop10.0\bin Adding toolboxes in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools Python is initially only aware of tools stored in ArcGIS system toolboxes like the Data Management Tools, Conversion Tools, and Analysis Tools toolboxes. Custom tools created by an individual, third party, or organization and stored in a custom toolbox can be accessed in the Python window like any system tool by importing the custom toolbox into the ArcPy site package. In the following example, the ImportToolbox function is used to allow tools contained in a custom toolbox to be accessed in Python. After importing the toolbox, the custom tools can be accessed as arcpy.<toolname>_<alias>. >>> arcpy.ImportToolbox("c:/mytools/geometrytools.tbx") >>> arcpy.CreateRegularPolygons_geometry( When a tool is accessed through the ArcPy site package, the toolbox alias where the tool is contained is a required suffix (arcpy.<toolname>_<alias>). Since ArcPy depends on toolbox aliases to access and execute the correct tool, aliases are extremely important when importing custom toolboxes. A good practice is to always define a custom toolbox's alias. However, if the toolbox alias is not defined, a temporary alias can be set as the second parameter of the ImportToolbox function. >>> arcpy.ImportToolbox("c:/mytools/geometrytools.tbx", "mytools") >>> arcpy.CreateRegularPolygons_mytools( Adding and removing server toolboxes Geoprocessing services can also be added to the scripting environment using ImportToolbox. Whether adding the geoprocessing service from a local or Internet server, the server and toolbox name are semicolon delimited. Learn more about geoprocessing services Sample syntax for adding a geoprocessing service # Import a geoprocessing service # import arcpy # To add a toolbox from a Internet server, provide the url and toolbox name # delimited by a semi-colon # arcpy.ImportToolbox("http://lab13/arcgis/services;BufferByVal") Sample syntax for adding a local geoprocessing service # Import a local geoprocessing service # import arcpy # To add a toolbox from a local server, provide the server and toolbox name # delimited by a semi-colon # arcpy.ImportToolbox("lab13;BufferByVal") Related Topics Using tools in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools Every geoprocessing tool has a fixed set of parameters that provide the tool with the information it needs for execution. Tools usually have input parameters that define the dataset or datasets that are typically used to generate new output data. Parameters have several important properties: Name Each tool parameter has a unique name. Type The type of data expected, such as feature class, integer, string, and raster. Direction The parameter defines either input or output values. Required Either a value must be provided for a parameter or it is optional. When a tool is used in a script, its parameter values must be correctly set so it can execute when the script is run. The documentation of each tool clearly defines its parameters and properties. Once a valid set of parameter values is provided, the tool is ready to be executed. Parameters are specified as either strings or objects. Strings are simply text that uniquely identifies a parameter value, such as a path to a dataset or a keyword. Most tool parameters can be specified as a simple string. For some parameters, such as a spatial reference, you can use an object instead of a string. In the following code example, input and output parameters are defined for the Buffer tool. Note that the tool name is always appended with its toolbox alias. In the example, two string variables are used to define the input and output parameters to make the call to the tool easier to read. import arcpy roads = "c:/St_Johns/data.gdb/roads" output = "c:/St_Johns/data.gdb/roads_Buffer" # Run Buffer using the variables set above and pass the remaining parameters # in as strings # arcpy.Buffer_analysis(roads, output, "distance", "FULL", "ROUND", "NONE") In the following code example, the CreateFeatureClass tool is executed using a spatial reference object for its optional Coordinate System parameter. The spatial reference object is created using the SpatialReference class, and its information is loaded from a projection file. import arcpy inputWorkspace = "c:/temp" outputName = "rivers.shp" # Create a spatial reference object # spatialRef = arcpy.SpatialReference() # Use a projection file to define the spatial reference's properties # spatialRef.createFromFile("c:/program files/arcgis/Desktop10.0/Coordinate Systems/" + \ "Projected Coordinate Systems/Continental/North America/North America Equidistant Conic.prj") # Run CreateFeatureclass using the spatial reference object # arcpy.CreateFeatureclass_management(inputWorkspace, outputName, "POLYLINE", "", "", "", spatialRef) Tool organization Geoprocessing tools are organized in two different ways. All tools are available as functions on ArcPy but are also available in modules matching the toolbox alias name. Although most of the examples in the help show tools organized as functions available from ArcPy, both approaches are equally valid. Which approach you use will come down to a matter of personal preference and coding habits. In the following example, the GetCount tool is shown using both approaches. import arcpy inFeatures = "c:/temp/rivers.shp" # Tools can be accessed as functions on the arcpy module, and # from modules matching the toolbox name. # arcpy.GetCount_management(inFeatures) arcpy.management.GetCount(inFeatures) When using tools in modules, sometimes you may want to draw attention to how a module is identified to make your script more readable. In this case, you can use the form from - import as. # Clean up street centerlines that were digitized without having set # proper snapping environments # import arcpy from arcpy import edit as EDIT from arcpy import management as DM streets = "c:/data/streets.gdb/majorrds" streetsCopy = "c:/output/Output.gdb/streetsBackup" DM.CopyFeatures(streets, streetsBackup) EDIT.TrimLine(streets, "10 Feet", "KEEP_SHORT") EDIT.ExtendLine(streets, "15 Feet", "EXTENSION") License: Spatial Analyst tools are handled differently to accommodate Map Algebra and are available only in the arcpy.sa module and not as functions on ArcPy. Getting results from a tool ArcPy returns the output values of a tool when it is executed as a Result object. The advantage of a result object is that you can maintain information about the execution of tools, including messages, parameters, and output. These results can be maintained even after several other tools have been run. The following examples show how to get the output from a result object following the execution of a geoprocessing tool. import arcpy arcpy.env.workspace = "D:/St_Johns/data.gdb" # Geoprocessing tools return a result object of the derived # output dataset. # result = arcpy.CopyFeatures_management("roads", "urban_roads") # A print statement will display the string # representation of the output. # print result # To get the output value, the result object has a getOutput method # resultValue = result.getOutput(0) Note: The result object's getOutput method returns a Unicode string from result objects that have output values. This is an important consideration when running a tool such as GetCount, which provides a count of records in a table, or CalculateDefaultClusterTolerance, which provides a cluster tolerance value. To convert the value to the expected type, it will have to be converted from a unicode string using built-in Python functions such as int() or float(). import arcpy from arcpy import env import types env.workspace = "c:/St_Johns/data.gdb" # Many geoprocessing tools return a result object of the derived # output dataset. A print statement will display the string # representation of the output. # result = arcpy.GetCount_management("roads") resultValue = result.getOutput(0) # The result object's getOutput method returns values as a # unicode string. To convert to a different Python type, use # built-in Python functions: str(), int(), long(), float() # count = int(resultValue) print count print types.TypeType(count) Result properties and methods Properties and methods Explanation inputCount Returns the number of inputs. outputCount Returns the number of outputs. messageCount Returns the number of messages. maxSeverity Returns the maximum severity. The returned severity can be 0 (no errors/warnings raised), 1 (warnings raised), or 2 (errors raised). resultID Returns the unique result ID. If the tool is not a geoprocessing service, the resultID will be "". status Returns the status of the job on the server. 0—New 1—Submitted 2—Waiting 3—Executing 4—Succeeded 5—Failed 6—Timed Out 7—Canceling 8—Canceled 9—Deleting 10—Deleted cancel() Cancels the job on the server. getInput(index) Returns a given input. If a record set or raster data object, a RecordSet or RasterData object is returned. getMapImageURL(ParameterList, Get map service image for a given output. Height, Width, Resolution) getMessage(index) Returns a specific message. getMessages(severity) The type of messages to be returned. 0=message, 1=warning, 2=error. Not specifying a value returns all message types. getOutput(index) Returns a given output. If a record set or raster data object, a RecordSet or RasterData object is returned. getSeverity(index) Result properties and methods Getting results from a server tool Returns the severity of a specific message. Like other geoprocessing tools, geoprocessing server tools have a fixed set of parameters that provide the tool with the information it needs for execution. When using asynchronous server tools in a script, the output can be retrieved by the result's getOutput method. Tip: The IsSynchronous function can be used to determine whether a tool is run synchronously or asynchronously. When a tool is synchronous, the results are automatically returned, but no other action may be taken until the tool has completed. In the following example, the GetParameterValue function is used to get a FeatureSet object from a server tool. This FeatureSet object contains the schema of the tool's input parameter. The FeatureSet object is then loaded with a feature class, and the server tool is executed on the server. The script ends by using the result object's getOutput method to get the tool output's, which is then saved locally by using the FeatureSet's save method. import arcpy import time # Add a toolbox from a server # arcpy.ImportToolbox("http://flame7/arcgis/services;GP/BufferByVal", "mytools") # Use GetParameterValue to get a featureset object with the default # schema of the first parameter of the tool 'bufferpoints' # inFeatureSet = arcpy.GetParameterValue("bufferpoints", 0) # Load a shapefile into the featureset # inFeatureSet.load("c:/base/roads.shp") # Run a server tool named BufferPoints with featureset created above # result = arcpy.BufferPoints_mytools(inFeatureSet, "5 feet") # Check the status of the result object every 0.2 seconds until it has a value # of 4 (succeeded) or greater # while result.status < 4: time.sleep(0.2) # Get the output FeatureSet back from the server and save to a local geodatabase # outFeatSet = result.getOutput(0) outFeatSet.save("c:/temp/base.gdb/towers_buffer") Getting a raster result from a server tool Raster results are returned as Tagged Image File Format (TIFF). By default, when using getOutput, the TIFF is written to your system's TEMP folder. To control the location of the TIFF, set the scratchWorkspace environment to a folder. import arcpy import time # Set the scratchworkspace to a folder. # arcpy.env.scratchWorkspace = "c:/temp/rasteroutput" # Add a toolbox from a server # arcpy.ImportToolbox("http://flame7/arcgis/services;SlopeByVal", "mytools") dem = "c:/dems/k_ne_g" # Run a server tool named RunSlope # result = arcpy.RunSlope_mytools(dem) # Check the status of the result object every 0.2 seconds until it has a value # of 4 (succeeded) or greater # while result.status < 4: print result.status time.sleep(0.2) # Raster output will be written to the scratchworkspace # outTIFF = result.getOutput(0) Getting a map image Geoprocessing services can have a result map service to create a digital map image of task results. Digital maps contain visual representations of geographic datasets that communicate information. Digital maps are transported across the Web as images (such as a .jpeg). A map image, byte for byte, contains far more human-interpretable information than raw features in a feature class. Map images are also manageable—they are easily compressed, they can be tiled into manageable chunks, and there are established methods for transporting and viewing them across the Web. Map images are created by an ArcGIS Server map service and are the result of publishing an ArcMap document (.mxd). Because of the characteristics of a map image, you may want to create one for the results of your geoprocessing task and transport the image across the Web rather than transporting the result dataset or datasets. Geoprocessing services can have a result map service used by ArcGIS Server to create map images of your output data. import arcpy import time import urllib # Add a toolbox from a server # arcpy.ImportToolbox("http://flame7/arcgis/services;GP/BufferByVal", "mytools") # Use GetParameterValue to get a featureset object with the default schema of the # first parameter of the tool 'bufferpoints' # inFeatureSet = arcpy.GetParameterValue("bufferpoints", 0) # Load a shapefile into the featureset # inFeatureSet.load("c:/base/roads.shp") # Run a server tool named BufferPoints with featureset created above # result = arcpy.BufferPoints_mytools(inFeatureSet, "5 feet") # Check the status of the result object every 0.2 seconds until it has a value # of 4 (succeeded) or greater # while result.status < 4: time.sleep(0.2) print result.status # Return a map service # mapimage = result.getMapImageURL(0) # Use Python's urllib module's urlretrieve method to copy the image locally # urllib.urlretrieve(mapimage, "c:/base/road_buffer.jpg") Related Topics Using functions in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools A function is a defined bit of functionality that does a specific task and can be incorporated into a larger program. In ArcPy, all geoprocessing tools are provided as functions, but not all functions are geoprocessing tools. In addition to tools, ArcPy provides a number of functions to better support geoprocessing workflows using Python. Functions can be used to list certain datasets, retrieve a dataset's properties, validate a table name before adding it to a geodatabase, or perform many other useful geoprocessing tasks. These functions are available only from ArcPy and not as tools in ArcGIS applications, since they are designed for Python workflows. The general form of a function is similar to that of tool; it takes arguments, which may or may not be required, and returns something. The returned value of a non-tool function can be varied—anything from strings to geoprocessing objects. Tool functions will always return a Result object and provide geoprocessing messages support. The following example uses two ArcPy functions, GetParameterAsText to receive an input argument, and Exists to determine whether the input exists or not. The Exists function returns a boolean value (either True or False). import arcpy input = arcpy.GetParameterAsText(0) if arcpy.Exists(input): print "Data exists" else: print "Data does not exist" The following example creates a Python list of feature classes using the ListFeatureClasses function, then loops through the list, clipping each individual feature class with a boundary feature class. import arcpy from arcpy import env import os # The workspace environment needs to be set before ListFeatureClasses # to identify which workspace the list will be based on # env.workspace = "c:/data" out_workspace = "c:/data/results/" clip_features = "c:/data/testarea/boundary.shp" # Loop through a list of feature classes in the workspace # for fc in arcpy.ListFeatureClasses(): # Set the output name to be the same as the input name, and # locate in the 'out_workspace' workspace # output = os.path.join(out_workspace, fc) # Clip each input feature class in the list # arcpy.Clip_analysis(fc, clip_features, output, 0.1) Related Topics Using classes in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools A class is analogous to an architectural blueprint. The blueprint provides the framework for how to create something. Classes can be used to create objects, often referred to as an instance. ArcPy classes, such as the SpatialReference and Extent classes, are often used as shortcuts to complete geoprocessing tool parameters that would otherwise have a more complicated string equivalent. ArcPy includes several classes, including SpatialReference, ValueTable, and Point. Once instantiated, its properties and methods may be used. Classes have one or more methods called constructors. A constructor is a method for initializing a new instance of a class. In the example below, SpatialReference(prjFile) is the class constructor—it creates the spatialRef object by reading a projection file. import arcpy prjFile = "c:/projections/North America Equidistant Conic.prj" spatialRef = arcpy.SpatialReference(prjFile) Like most other classes, SpatialReference contains a number of methods and properties. Building on the previous sample, you can access the properties of spatialRef. import arcpy prjFile = "c:/projections/North America Equidistant Conic.prj" spatialRef = arcpy.SpatialReference(prjFile) # Print the SpatialReference's name, and type # print spatialRef.name print spatialRef.type Classes can be used repeatedly; in the following example, two unique point objects are created by using the Point class. import arcpy pointA = arcpy.Point(2.0, 4.5) pointB = arcpy.Point(3.0, 7.0) Note: The CreateObject function can also be used to create many of the objects that can be created using classes. However, using classes is both easier to use and more readable. Using classes with geoprocessing tools Tool parameters are usually defined using simple text strings. Dataset names, paths, keywords, field names, tolerances, and domain names can be specified using a quoted string. Some parameters are harder to define using simple strings; they are more complex parameters that require many properties. Instead of using long, complicated text strings to define these parameters, you can use classes (for example, SpatialReference, ValueTable, and Point classes). The documentation for each tool contains a scripting example of how each tool parameter is defined and used. In the following example, a SpatialReference object is created and used to define the output coordinate system of a new feature class created using the CreateFeatureClass tool. import arcpy inputWorkspace = "c:/temp" outputName = "rivers.shp" prjFile = "c:/projections/North America Equidistant Conic.prj" spatialRef = arcpy.SpatialReference(prjFile) # Run CreateFeatureclass using the spatial reference object # arcpy.CreateFeatureclass_management(inputWorkspace, outputName, "POLYLINE", "", "", "", spatialRef) The string equivalent for this parameter looks something like this: PROJCS['North_America_Equidistant_Conic',GEOGCS['GCS_North_American_1983',DATUM['D_No rth_American_1983',SPHEROID['GRS_1980',6378137.0,298.257222101]],PRIMEM['Greenwich',0 .0],UNIT['Degree',0.0174532925199433]],PROJECTION['Equidistant_Conic'],PARAMETER['Fal se_Easting',0.0],PARAMETER['False_Northing',0.0],PARAMETER['Central_Meridian',96.0],PARAMETER['Standard_Parallel_1',20.0],PARAMETER['Standard_Parallel_2',60.0],PAR AMETER['Latitude_Of_Origin',40.0],UNIT['Meter',1.0]];IsHighPrecision Related Topics Using environment settings in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools Each tool has a set of parameters it uses to execute an operation. Some of these parameters are common among all tools, such as a tolerance or output location. These parameters may obtain their default values from a geoprocessing environment that all tools utilize during their operation. When a tool is executed, the current environment settings can also be used as global input parameter values. Settings such as an area of interest, the spatial reference of the output dataset, and the cell size of a new raster dataset can all be specified with geoprocessing environments. A script can be executed in several different ways. It can be run as a script tool in an ArcGIS application, such as ArcMap. It can also be run from another script or by itself from a Python window. When a script is run inside a tool from an ArcGIS application or from another geoprocessing script, the environment settings used by the calling application or script are passed to it. These settings become the default settings used by the tool's script when it is executed. The called script may alter the settings passed to it, but those changes are only used within that script or by any other tool it may call. Changes are not passed back to the calling script or application. The environment model can best be described as cascading, where values flow down to any process that uses the geoprocessing environment. Getting and setting environment settings Environment settings are exposed as properties on the env class. These properties can be used to retrieve the current values or to set them. Each environment setting has a name and a label. Labels are displayed on the Environment Settings dialog box in ArcGIS. Names are used in scripts or at the command line in ArcGIS applications. Below are examples of how to use environment values: Note: Environments can be accessed as read/write properties from the environment class, as arcpy.env.<environmentName>. Alternatively, instead of prefixing each environment name with arcpy.env, you can simplify your code by taking advantage of Python's from-import statement. This alternative has the advantage of simplifying your code and making it easier to read. import arcpy import arcpy from arcpy import env import arcpy from arcpy import env arcpy.env.workspace = "c:/data" env.workspace = "c:/data" Example 1: Setting environment values import arcpy from arcpy import env # Set the workspace environment setting # env.workspace = "c:/St_Johns/data.gdb" # Set the XYTolerance environment setting # env.XYTolerance = 2.5 # Calculate the default spatial grid index, divide in half, then # set the spatial grid 1 environment setting # result = arcpy.CalculateDefaultGridIndex_management("roads") env.spatialGrid1 = float(result.getOutput(0)) / 2 # Clip the roads by the urban area feature class # arcpy.Clip_analysis("roads","urban_area","urban_roads") Example 2: Getting and setting an environment value import arcpy from arcpy import env # Check the current raster cell size and make sure it is a certain size # for standard output # env.workspace = "c:/avalon/data" if env.cellSize < 10: env.cellSize = 10 elif env.cellSize > 20: env.cellSize = 20 arcpy.HillShade_3d("island_dem", "island_shade", 300) Caution: Spelling and case count when setting environment values. Assigning a value to arcpy.env.Workspace is not the same as setting arcpy.env.workspace (note: arcpy.env.workspace is the correct form). If you encounter a case where you've set an environment but are not seeing the effect on subsequent tools, check the spelling and case. The ListEnvironments function can be used to check proper environment names. import arcpy print arcpy.ListEnvironments() Saving and loading settings Automatic transfer of settings is only done when a script is executed by a geoprocessing tool. When a geoprocessing script calls another geoprocessing script, the environments are not automatically passed to the called script, since there is no way for the first script to know that the second script is using ArcPy. To facilitate the transfer of environment settings from one script to another and to save settings from one session to the next, settings can be saved to a file. ArcPy can then set its environments by loading a settings file. In the first example below, a script transfers its settings to a second script by saving them to a file and passing that file name as a parameter to a second script. The second example loads an environment settings file using a name passed as a script argument. Example 1: # Import ArcPy site-package # import arcpy from arcpy import env import os # Set the raster environment settings and the workspace # env.cellSize = 25 env.mask = "D:/St_Johns/Landcover" env.workspace = "D:/St_Johns" # Save the environment settings # envfile = arcpy.SaveSettings("c:/St_Johns/settings") # Call Python script and pass file name as argument # os.system('MyHillshade.py ' + envfile) Example 2: # Import ArcPy site-package # import arcpy # Get the input parameter value # envfile = arcpy.GetParameterAsText(0) # Load the environment settings # arcpy.LoadSettings(envfile) # Calculate hillshade # arcpy.Hillshade_3d("city_dem","city_shade",250) Environment values can be passed between modules as arguments. Saving and loading settings between executing modules is not an efficient way of sharing values. Using a settings file is valid when used by modules that are not run together, which is the intent of the above example. Related Topics Understanding message types and severity Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools During execution of a tool, messages are written that can be retrieved with geoprocessing functions, such as GetMessages(). These messages include such information as the following: When the operation started and ended The parameter values used General information about the operation's progress (information message) Warnings of potential problems (warning message) Errors that cause the tool to stop execution (error message) All communication between tools and users is done with messages. Depending on where you are running the tools from, messages appear in the Results window, the Python window, and the progress dialog box. From Python, you can fetch these messages within your script, interrogate them, print them, or write them to a file. All messages have a severity property, either informative, warning, or error. The severity is an integer where 0 = informative, 1 = warning, and 2 = error. Severity Informative An informative message is just that—information about execution. It is never message used to indicate problems. Only general information, such as a tool's progress, (severity = 0) what time a tool started or completed, output data characteristics, or tool results, is found in informative messages. Warning Warning messages are generated when a tool experiences a situation that may message cause a problem during its execution or when the result may not be what you (severity = 1) expect. For example, defining a coordinate system for a dataset that already has a coordinate system defined generates a warning. You can take action when a warning is returned, such as canceling the tool's execution or making another parameter choice. Error message Error messages indicate a critical event that prevented a tool from executing. (severity = 2) Errors are generated when one or more parameters have invalid values or when a critical execution process or routine has failed. Both warning and error messages are accompanied by a six-digit ID code. These ID codes have been documented to provide additional information on their causes and how they can be dealt with. When error or warning codes are shown in the tool or progress dialog box, Python window, or Result window, they have a link that allows you to go directly to the additional help for that message. Getting messages Messages from the last tool executed are maintained by ArcPy and can be retrieved using the GetMessages function. This function returns a single string containing all the messages from the tool that was last executed. The returned messages can be filtered to include only those with a certain severity using the severity option. When using ArcPy, the first message gives the tool executed, and the last message gives the ending and elapsed time for the tool's execution. The tool's second and last messages always give the start and end time, respectively, for the tool's execution. Learn more about the GetMessageCount functionLearn more about the GetMessage functionLearn more about the GetMessages functionLearn more about the AddError functionLearn more about the AddIDMessage functionLearn more about the AddMessage functionLearn more about the AddReturnMessage functionLearn more about the AddWarning function Getting geoprocessing messages import arcpy # Execute the GetCount tool # arcpy.GetCount_management("c:/base/data.gdb/roads") # Get the resulting messages and print them # print arcpy.GetMessages() # The returned messages would look similar to the following: # Executing: GetCount c:/base/data.gdb/roads # Start Time: Wed Apr 07 11:28:21 2010 # Row Count = 373 # Succeeded at Wed April 07 11:28:21 2010 (Elapsed Time: 0.00 seconds) Individual messages can be retrieved using the GetMessage function. This function has one parameter, which is the index position of the message. The GetMessageCount function returns the number of messages from the last tool executed. The example below shows how to print information about which tool was executed along with ending and elapsed times for the tool. import arcpy arcpy.env.workspace = "D:/base/data.gdb" arcpy.Clip_analysis("roads", "urban_area", "urban_roads") # Print the first message - tool executed # print arcpy.GetMessage(0) # Print the last message - ending and elapsed times for tool # print arcpy.GetMessage(arcpy.GetMessageCount - 1) Getting messages from a result object Messages can also be accessed from a tool using a Result object. Unlike getting messages from ArcPy, messages on a Result object can be maintained even after running multiple tools. The Result object supports several of the same functions used to get and interpret geoprocessing tool messages. Result properties and methods Properties and methods Explanation inputCount Returns the number of inputs. outputCount Returns the number of outputs. messageCount Returns the number of messages. maxSeverity Returns the maximum severity. The returned severity can be 0 (no errors/warnings raised), 1 (warnings raised), or 2 (errors raised). resultID Returns the unique result ID. If the tool is not a geoprocessing service, the resultID will be "". status Returns the status of the job on the server. 0—New 1—Submitted 2—Waiting 3—Executing 4—Succeeded 5—Failed 6—Timed Out 7—Canceling 8—Canceled 9—Deleting 10—Deleted cancel() Cancels the job on the server. getInput(index) Returns a given input. If a record set or raster data object, a RecordSet or RasterData object is returned. getMapImageURL(ParameterList, Get map service image for a given output. Height, Width, Resolution) getMessage(index) Returns a specific message. getMessages(severity) The type of messages to be returned. 0=message, 1=warning, 2=error. Not specifying a value returns all message types. getOutput(index) Returns a given output. If a record set or raster data object, a RecordSet or RasterData object is returned. getSeverity(index) Returns the severity of a specific message. Result properties and methods The following sample runs two geoprocessing tools but waits until the tools are executed before reviewing the messages. import arcpy arcpy.env.workspace = "D:/base/data.gdb" # Execute the Clip and GetCount tools # clipResult = arcpy.Clip_analysis("roads", "urban_area", "urban_roads") countResult = arcpy.GetCount_management("urban_roads") # Get the resulting messages and print them # print clipResult.getMessages() print countResult.getMessages() As with geoprocessing tools, server tool messages are classified as either information, a warning, or an error. A message's type is indicated by its severity property, which is a numeric value. The following sample shows how to get the messages from a server tool after it has completed. import arcpy import time # Add the server toolbox # arcpy.ImportToolbox("http://lab13/arcgis/services;BufferByVal", "mytools") featset = arcpy.FeatureSet() featset.load("//flames/gpqa/coredata/global/redlands/control.shp") # Run a server tool named BufferPoints # result = arcpy.BufferPoints_mytools(featset, "1000 feet") # Wait until the tool completes # while result.status < 4: time.sleep(0.2) # Print all messages from the result object # print result.getMessages() Related Topics Error handling with Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools Errors happen. Writing scripts that expect and handle errors can save you a lot of time and frustration. When a tool returns an error message, ArcPy generates a system error, or exception. In Python, you can provide a variety of structures and methods that can handle exceptions. Of course, a script can fail for many other reasons that are not specifically related to a geoprocessing tool; these too need to be caught and dealt with in an appropriate manner. The following sections offer a few techniques that introduce the basics of Python exception handling. When a tool writes an error message, ArcPy generates a system error, or an exception. Python allows you to write a routine that is automatically run whenever a system error is generated. Within this errorhandling routine, you can retrieve the error message from ArcPy and react accordingly. If a script does not have an error-handling routine, it fails immediately, which decreases its robustness. Use errorhandling routines to manage errors and improve a script's usability. Geoprocessing tool error messages are accompanied by a six-digit code. These ID codes have been documented to provide additional information on their cause and how they can be dealt with. Learn more about creating and debugging geoprocessing scriptsLearn more about script tools try-except statement A try-except statement can be used to wrap entire programs or just particular portions of code to trap and identify errors. If an error occurs within the try statement, an exception is raised, and the code under the except statement is then executed. Using a simple except statement is the most basic form of error handling. In the following code, Buffer fails because the required Distance parameter has not been used. Instead of failing without explanation, the except statement is used to trap the error, then fetch and print the error message generated by Buffer. Note that the except block is only executed if Buffer returns an error. import arcpy try: # Execute the Buffer tool # arcpy.Buffer_analysis("c:/transport/roads.shp", "c:/transport/roads_buffer.shp") except Exception as e: print e.message # If using this code within a script tool, AddError can be used to return messages # back to a script tool. If not, AddError will have no effect. arcpy.AddError(e.message) The try statement has an optional finally clause that can be used for tasks that should be always be executed, whether an exception has occurred or not. In the following example, the 3D Analyst extension is checked back in under a finally clause, ensuring that the extension is always checked back in. class LicenseError(Exception): pass import arcpy from arcpy import env try: if arcpy.CheckExtension("3D") == "Available": arcpy.CheckOutExtension("3D") else: # Raise a custom exception # raise LicenseError env.workspace = "D:/GrosMorne" arcpy.HillShade_3d("WesternBrook", "westbrook_hill", 300) arcpy.Aspect_3d("WesternBrook", "westbrook_aspect") except LicenseError: print "3D Analyst license is unavailable" except: print arcpy.GetMessages(2) finally: # Check in the 3D Analyst extension # arcpy.CheckInExtension("3D") raise statement The previous example dealt with handling an exception that occurred in the code; in some cases, it may be necessary to create custom exceptions. A raise statement can be used for this purpose. In the following code, a raise statement is used when an input feature class has been identified as having no features. This is not strictly an error but a condition that the code can be used to guard against. class NoFeatures(Exception): pass import arcpy import os arcpy.env.overwriteOutput = 1 fc = arcpy.GetParameterAsText(0) try: # Check that the input has features # result = arcpy.GetCount_management(fc) if int(result.getOutput(0)) > 0: arcpy.FeatureToPolygon_management(fc, os.path.dirname(fc) + os.sep + "out_poly.shp") else: # Raise custom exception # raise NoFeatures(result) except NoFeatures: # The input has no features # print fc + " has no features." except: # By default any other errors will be caught here # print arcpy.GetMessages(2) ExecuteError class When a geoprocessing tool fails, it throws an ExecuteError exception class. What this means is that you can divide errors into two groups, geoprocessing errors (those that throw the ExecuteError exception) and everything else. You can then handle the errors differently, as demonstrated in the code below: import arcpy try: result = arcpy.GetCount_management("C:/invalid.shp") # Return geoprocessing specific errors # except arcpy.ExecuteError: arcpy.AddError(arcpy.GetMessages(2)) # Return any other type of error except: arcpy.AddError("Non-tool error occurred") traceback In larger, more complex scripts, it can be difficult to determine the precise location of an error. Python's sys and traceback modules can be used together to isolate the exact location and cause of the error, identifying the cause of an error more accurately and saving you valuable debugging time. # Import the required modules # import arcpy import sys import traceback arcpy.env.workspace = "C:/Data/myData.gdb" try: arcpy.CreateSpatialReference_management() #-------------------------# Your code goes here # # See the table below for examples #-------------------------except arcpy.ExecuteError: # Get the tool error messages # msgs = arcpy.GetMessages(2) # Return tool error messages for use with a script tool # arcpy.AddError(msgs) # Print tool error messages for use in Python/PythonWin # print msgs except: # Get the traceback object # tb = sys.exc_info()[2] tbinfo = traceback.format_tb(tb)[0] # Concatenate information together concerning the error into a message string # pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1]) msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n" # Return python error messages for use in script tool or Python Window # arcpy.AddError(pymsg) arcpy.AddError(msgs) # Print Python error messages for use in Python / Python Window # print pymsg + "\n" print msgs If the above code was used and a geoprocessing tool error occurred, such an invalid input, this would raise ExecuteError, and the first except statement would be used. This statement would print out the error messages using the GetMessages function. If the same code was used, but a different type of error occurred, the second except statement would be used. Instead of printing geoprocessing messages, it would get a traceback object and print out the appropriate system error messages. The table below shows the expected errors that result from three different lines of codes that could be substituted into the code above. The first is a geoprocessing tool error, which prints out the traceback information and the geoprocessing error messages. The second and third examples are not specifically caught and print out only the traceback information. Your code arcpy.GetCount_management("") Resulting error PYTHON ERRORS: Traceback info: File "c:\temp\errortest.py", line 10, in <module> arcpy.GetCount_management("") Error Info: Failed to execute. Parameters are not valid. ERROR 000735: Input Rows: value is required Failed to execute (GetCount). ArcPy ERRORS: Failed to execute. Parameters are not valid. ERROR 000735: Input Rows: value is required Failed to execute (GetCount). x = "a" + 1 PYTHON ERRORS: Traceback info: File "c:\temp\errortest.py", line 10, in <module> x = "a" + 1 Error Info: cannot concatenate 'str' and 'int' objects float("a text string") PYTHON ERRORS: Traceback info: File "c:\temp\errortest.py", line 10, in <module> float("a text string") Error Info: invalid literal for float(): a text string Error results Related Topics Setting paths to data in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools Programming languages, such as Python, treat a backslash (\) as an escape character. For instance, \n represents a line feed, and \t represents a tab. When specifying a path, a forward slash (/) can be used in place of a backslash. Two backslashes can be used instead of one to avoid a syntax error. A string literal can also be used by placing the letter r before a string containing a backslash so it is interpreted correctly. Example 1: Valid use of paths in Python import arcpy arcpy.GetCount_management("c:/temp/streams.shp") arcpy.GetCount_management("c:\\temp\\streams.shp") arcpy.GetCount_management(r"c:\temp\streams.shp") Example 2: Invalid use of paths in Python In the following sample, backslashes are used by mistake, and \t is interpreted as a tab by Python. GetCount will fail, as the path is interpreted differently than it was intended. import arcpy arcpy.GetCount_management("c:\temp\streams.shp") # ExecuteError: Failed to execute. Parameters are not valid. # ERROR 000732: Input Rows: Dataset c: em\streams.shp does not exist or is not supported # Failed to execute (GetCount) Tip: It is possible to have a feature class and a feature dataset with the same name contained within a geodatabase. In such a case, the feature class and feature dataset will have the same ArcCatalog path. Most tools work with one or the other. However, for those tools that can work with either, such as the Copy tool, the data type can be specified to avoid ambiguity. Related Topics Paths explained: Absolute, relative, UNC, and URL Listing tools, toolboxes, and environment settings Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools Depending on which toolboxes are available, ArcPy might have access to several toolboxes, dozens of environment settings, and hundreds of tools. ArcPy has several appropriately named functions to return a list of tools (ListTools), environment settings (ListEnvironments), or toolboxes (ListToolboxes). Learn more about the ListEnvironments functionLearn more about the ListToolboxes functionLearn more about the ListTools function Each function has a wild card option and returns a list of name strings that can be looped through. The example below shows how to access available tools and print out their usage. import arcpy # Create a list of the conversion tools # tools = arcpy.ListTools("*_conversion") # Loop through the list and print each tool's usage # e.g., 'Usage: merge <inputs;inputs...> <output> {field_mappings}' # for tool in tools: print arcpy.Usage(tool) The following sample provides an approach for viewing environment settings in Python. import arcpy environments = arcpy.ListEnvironments() # Sort the environment list, disregarding capitalization # environments.sort(key=string.lower) for environment in environments: # Use Python's eval function to evaluate an environment's value # envSetting = eval("arcpy.env." + environment) # Format and print each environment and its current setting # print "%-30s: %s" % (environment, envSetting) The following sample provides an approach for viewing current toolboxes in Python. import arcpy # Print all current toolboxes # for toolbox in arcpy.ListToolboxes(): # Toolboxes are printed in the form of "toolbox_name(toolbox_alias)" print toolbox Related Topics Listing data Accessing licenses and extensions in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing tools Whenever a tool is executed in a script, an ArcGIS Desktop license is required. Tools from ArcGIS extensions, such as ArcGIS Spatial Analyst, require an additional license for that extension. If the necessary licenses are not available, a tool fails and returns error messages. For example, if you install with an ArcView license, and you attempt to execute a tool set for an ArcEditor or ArcInfo license, the tool will fail. When using an ArcView or ArcEditor license, a script should set the product to ArcView or ArcEditor. Likewise, when using an Engine or EngineGeoDB license, a script should set the product to Engine or EngineGeoDB. If a license is not explicitly set, the license will be initialized based on the highest available license level the first time an ArcPy tool, function, or class is accessed. Every tool checks to ensure it has the appropriate license. If it doesn't have what's required, it fails. To guard against the situation of executing part way through and failing, you can perform a check at the top of your script and fail immediately. Tip: The setting of the product and extensions is only necessary within stand-alone scripts. If you are running tools from the Python window or using script tools, the product is already set from within the application, and the active extensions are based on the Extensions dialog box. Desktop, Engine/Server licenses Product modules are imported prior to the import of arcpy to define the desktop license used by a script. The CheckProduct function can be used to the check the availability of desktop licenses, while the ProductInfo function reports what the current product license is. Legacy: The product level should be set by importing the appropriate product module (arcinfo, arceditor, arcview, arcserver, arcenginegeodb, arcengine) prior to importing arcpy. The SetProduct function is a legacy function and cannot set the product once arcpy has been imported. Extension licenses Licenses for extensions can be retrieved from a license manager and returned once they are no longer needed. CheckExtension is used to see if a license is available to be checked out for a specific type of extension, while CheckOutExtension actually retrieves the license. Once the extension license has been retrieved by the script, extension tools can be executed. Once a script is done using tools from a particular extension, the CheckInExtension function should be used to return the license to the license manager so other applications can use it. All checked-out extension licenses and set product licenses are returned to the license manager when a script completes. The following example executes some ArcGIS 3D Analyst tools and sets the desktop product license to ArcView, since an ArcInfo license is not required to execute tools from an extension. The script will fail if the ArcView license is not explicitly set and no ArcInfo license is available, since a desktop license is required to execute extension tools. class LicenseError(Exception): pass # Set desktop license used to ArcView # import arcview import arcpy from arcpy import env try: if arcpy.CheckExtension("3D") == "Available": arcpy.CheckOutExtension("3D") else: # Raise a custom exception # raise LicenseError env.workspace = "D:/GrosMorne" arcpy.HillShade_3d("WesternBrook", "westbrook_hill", 300) arcpy.Aspect_3d("WesternBrook", "westbrook_aspect") except LicenseError: print "3D Analyst license is unavailable" except: print arcpy.GetMessages(2) finally: # Check in the 3D Analyst extension # arcpy.CheckInExtension("3D") In the above example, the 3D Analyst extension is checked in under a finally clause, ensuring that the extension is always checked back in, whether an exception has occurred or not. A returned value of Failed, Unavailable or NotLicensed indicates that the extension could not be successfully checked out. Below are the extension names and their extension code names: Extension Extension Code 3D Analyst 3D ArcGIS Schematics Schematics ArcScan ArcScan Business Analyst Business Data Interoperability DataInteroperability Geostatistical Analyst GeoStats ArcGIS Workflow Manager JTX Network Analyst Network Esri Aeronautical Solution Aeronautical Esri Defense Mapping Defense Esri Production Mapping Foundation ArcGIS Data Reviewer Datareviewer Esri Nautical Solution Nautical Spatial Analyst Spatial StreetMap StreetMap Tracking Analyst Tracking Product code names Product Codes ArcInfo ArcEditor ArcView Engine EngineGeoDB ArcServer Licensing functions Function Explanation CheckExtension(extension) Checks to see if a license is available to be checked out for a specific type of extension. Return Value Available Meaning The requested license is available to be set. Unavailable The requested license is unavailable to be set. NotLicensed The requested license is not valid. Failed A system failure occurred during the request. CheckInExtension(extension) Returns the license so other applications can use it. Return Value Meaning NotInitialized No desktop license has been set. Failed A system failure occurred during the request. CheckedIn The license has been returned successfully. CheckOutExtension(extension) Retrieves the license. Return Value Meaning NotInitialized No desktop license has been set. Unavailable The requested license is unavailable to be set. CheckedOut CheckProduct(code) Successfully set the license. Checks to see if the requested license is available. Return Value Meaning AlreadyInitialized License has already been set in the script. Available The requested license is available to be set. Unavailable The requested license is unavailable to be set. NotLicensed The requested license is not valid. Failed A system failure occurred during the request. ProductInfo() Returns the current product license. Return Value Meaning NotInitialized No license has been set. ArcInfo An ArcInfo license has been set. ArcEditor An ArcEditor license has been set. ArcView An ArcView license has been set. ArcServer An ArcGIS Server license has been set. EngineGeoDB An EngineGeoDB license has been set. Engine SetProduct(code) An Engine license has been set. Defines the desktop license. Return Value Meaning CheckedOut Successfully set the license. AlreadyInitialized License has already been set in the script. NotLicensed The requested license is not valid. Failed A system failure occurred during the request. Listing data Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Working with sets of data in Python One of the foremost tasks in a batch processing script is cataloging the available data so it can iterate through the data during processing. ArcPy has a number of functions built specifically for creating such lists. ListFields(dataset, wild_card, field_type) Returns a list of fields found in the input value ListIndexes(dataset, wild_card) Returns a list of attribute indexes found in the input value ListDatasets(wild_card, feature_type) Returns the datasets in the current workspace ListFeatureClasses(wild_card, Returns the feature classes in the current workspace feature_type) ListFiles(wild_card) Returns the files in the current workspace ListRasters(wild_card, raster_type) Returns a list of rasters found in the current workspace ListTables(wild_card, table_type) Returns a list of tables found in the current workspace ListWorkspaces(wild_card, Returns a list of workspaces found in the current workspace_type) workspace ListVersions(sde_workspace) Returns a list of versions the connected user has permission to use List functions The result of each of these functions is a Python list, which is a list of values. A list in scripting can contain any type of data, such as a string, which could be, for example, a path to a dataset, field, or row from a table. Once the list has been created with the values you want, you can loop through it in your script to work with each individual value. Learn more about listing tools, toolboxes, and environment settings List function parameters The parameters of these functions are similar. A few, such as ListFields, require an input dataset value, since the items the functions are listing reside within a certain object or dataset. Other functions do not require an input dataset, because they list types of data in the current workspace that are defined in the environment settings. All functions have a wildcard parameter, which is used to restrict the objects or datasets listed by name. A wildcard defines a name filter, and all the contents in the newly created list must pass that filter. For example, you may want to list all the feature classes in a workspace that start with the letter G. The following example shows how this is done: import arcpy from arcpy import env # Set the workspace. List all of the feature classes that start with 'G' # env.workspace = "D:/St_Johns/data.gdb" fcs = arcpy.ListFeatureClasses("G*") The list can also be restricted to match certain data properties, such as only polygon feature classes, integer fields, or coverage datasets. This is what the Type parameter is used for in all the functions. In the next example, the feature classes in a workspace are filtered using a wild card and a data type, so only polygon feature classes that start with the letter G are in the resulting list: # Set the workspace. List all of the polygon feature classes that # start with 'G' # env.workspace = "D:/St_Johns/data.gdb" fcs = arcpy.ListFeatureClasses("G*", "polygon") Using your list ArcPy uses a Python list type as the returned type for all its list function results, since lists support the flexibility required for simple data access and multiple data types. A For loop is ideal for working with a Python list because it can be used to step through the list one item at a time. A For loop iterates through each item in the list. Below is an example of a For loop used to iterate through the list generated in the previous example: # For each feature class in the list of feature classes # for fc in fcs: # Copy the features from the workspace to a folder # arcpy.CopyFeatures_management(fc, "D:/St_Johns/Shapefiles/” + fc) Following is another example of how to use a List function. The script is used to create raster pyramids for all rasters that are Tagged Image File Format (TIFF) images within a folder. # Set the workspace. List all of the TIFF files # env.workspace= "D:/St_Johns/images" # For each raster in the list of rasters # for tiff in arcpy.ListRasters("*", "TIF"): # Create pyramids # arcpy.BuildPyramids_management(tiff) A Python list provides the opportunity to use and manage the results of a list function in variety of ways. Lists are a versatile Python type and provide a number of methods (append, count, extend, index, insert, pop, remove, reverse, sort) that can be used to manipulate and extract information. For instance, if you want to know how many feature classes you have in a workspace, you can use Python's built-in len function to provide that number. import arcpy from arcpy import env env.workspace = "c:/St_Johns/Shapefiles" fcs = arcpy.ListFeatureClasses() # Use Python's built-in function len to reveal the number of feature classes # in the workspace # fcCount = len(fcs) print fcCount Tip: A Python list can show its contents easily. Python lists can be manipulated with a number of methods, including sort, append, and reverse. >>> import arcpy >>> from arcpy import env >>> env.workspace = "c:/data/water.gdb" >>> fcs = arcpy.ListFeatureClasses() >>> print fcs [u'water_pipes', u'water_services', u'water_stations'] >>> fcs.sort(reverse=True) >>> print fcs [u'water_stations', u'water_services', u'water_pipes'] As lists are an ordered collection, they also permit indexing and slicing. >>> print fcs[0] water_stations >>> print fcs[1:] [u'water_services', u'water_pipes'] List function type keywords The default behavior for all list functions is to list all supported types. A keyword is used to restrict the returned list to a specific type. The type keywords for each function are listed in the table below. Function Type keywords ListDatasets All, Feature, Coverage, RasterCatalog, CAD, VPF, TIN, Topology ListFeatureClasses All, Point, Label, Node, Line, Arc, Route, Polygon, Region ListFields All, SmallInteger, Integer, Single, Double, String, Date, OID, Geometry, BLOB ListTables All, dBASE, INFO ListRasters All, ADRG, BIL, BIP, BSQ, BMP, CADRG, CIB, ERS, GIF, GIS, GRID, STACK, IMG, JPEG, LAN, SID, SDE, TIFF, RAW, PNG, NITF ListWorkspaces All, Coverage, Access, SDE, Folder Type keywords for List functions Example: Using list functions to migrate from personal to file geodatabases A common conversion task is the large-scale transfer of data from one format to another. The following script takes advantage of ListWorkspaces, ListFeatureClasses, ListTables, and ListDatasets to identify all personal geodatabases in a folder and converts the feature datasets, feature classes, and tables of each to file geodatabases. import arcpy from arcpy import env import os # Allow for the overwriting of file geodatabases, if they already exist # env.overwriteOutput = True # Set workspace to folder containing personal geodatabases # env.workspace = arcpy.GetParameterAsText(0) # Identify personal geodatabases # for pgdb in arcpy.ListWorkspaces("", "Access"): # Set workspace to current personal geodatabase # env.workspace = pgdb # Create file geodatabase based on personal geodatabase # fgdb = pgdb[:-4] + ".gdb" arcpy.CreateFileGDB_management(os.path.dirname(fgdb), os.path.basename(fgdb)) # Identify feature classes and copy to file gdb # for fc in arcpy.ListFeatureClasses(): print "Copying feature class " + fc + " to " + fgdb arcpy.Copy_management(fc, fgdb + os.sep + fc) # Identify tables and copy to file gdb # for table in arcpy.ListTables(): print "Copying table " + table + " to " + fgdb arcpy.Copy_management(table, fgdb + os.sep + table) # Identify datasets and copy to file gdb # Copy will include contents of datasets # for dataset in arcpy.ListDatasets(): print "Copying dataset " + dataset + " to " + fgdb arcpy.Copy_management(dataset, fgdb + os.sep + dataset) Related Topics Listing tools, toolboxes, and environment settings Working with multivalue inputs Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Working with sets of data in Python Many geoprocessing tools have input parameters that accept multiple values. When you view the tool's reference page or its usage in the Python window, whenever you see the parameter enclosed in brackets [ ], you know it can take a list of values. For example, the Delete Field tool takes a list of fields to delete and the parameter usage is displayed as [drop_field, ...]. Some parameters, such as the input_features parameter of the Union tool, take a list-of-lists; its usage is displayed as [[in_features, {Rank}], ...]. Any parameter that accepts a list of values (or a list of list of values) is a multivalue parameter—it accepts one or more values. There are three ways to specify a multivalue parameter: 1. As a Python list, where each value is an element in the list 2. As a string, where values are separated by semicolons 3. As a ValueTable, where values are stored in a virtual table of rows and columns Below are examples of each. As a Python list In a script, multivalue inputs can be passed as a Python list. A list is enclosed in brackets and is a flexible Python type. DeleteFields using a Python list for the drop_field parameter import arcpy from arcpy import env env.workspace = "C:/base/county.gdb" arcpy.DeleteField_management("roads", ["STREET_NAM", "LABEL", "CLASS"]) Union using a Python list for the in_features parameter import arcpy from arcpy import env env.workspace = "C:/base/data/gdb" arcpy.Union_analysis([["counties", 2],["parcels", 1]], "state_landinfo") As a string Your script may have to use a multivalue string in some cases, because one may be returned as an output value of a tool or passed as an input parameter for your script. DeleteFields using a multivalue string for the drop_field parameter. import arcpy from arcpy import env env.workspace = "C:/base/county.gdb" arcpy.DeleteField_management("roads", "STREET_NAM;LABEL;CLASS") Union using a multivalue string for the in_features parameter import arcpy from arcpy import env env.workspace = "C:/base/data/gdb" arcpy.Union_analysis("counties 2;parcels 1", "state_landinfo") With ValueTable A ValueTable allows you to organize values into a virtual table of rows and columns. You specify the number of columns when you create a value table. The default is a single column. DeleteFields using a ValueTable for the drop_field parameter import arcpy from arcpy import env env.workspace = "C:/base/county.gdb" vt = arcpy.ValueTable() vt.addRow("STREET_NAM") vt.addRow("LABEL") vt.addRow("CLASS") arcpy.DeleteField_management("roads", vt) Union using a ValueTable for the in_features parameter import arcpy from arcpy import env env.workspace = "C:/base/data/gdb" vt = arcpy.ValueTable(2) vt.addRow("counties 2") vt.addRow("parcels 1") arcpy.Union_analysis(vt, "state_landinfo") Related Topics Using the multivalue parameter control Mapping input fields to output fields Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Working with sets of data in Python A common geoprocessing task is to merge many datasets into a new or existing dataset to create a single dataset covering a larger area or a table containing a greater number of records. Often, the attributes, or fields, are the same for all the inputs that are used in a merge or append operation; sometimes, however, they do not match, and the relationships between fields of different names and types have to be mapped. For an example of field mappings, see the Merge tool in the Data Management toolbox; it facilitates this mapping of relationships so data is placed in the desired output fields with the correct values. The FieldMap object provides a field definition and a list of input fields from a set of tables or feature classes that provide its values. The properties of the FieldMap object include the start and end position of an input text value, so a new output value can be created using a slice of an input value. If a FieldMap object contains multiple input fields from the same table or feature class, each record's values are merged using the mergeRule property. This is a convenient way to join values, such as a street name that is held in one field and a street type that is held in another, for example, Eureka and Street. The joinDelimiter property of FieldMap is used if the mergeRule value Join is specified. Any set of characters, such as a space, can be used as a delimiter. In the above example, this would create a value of Eureka Street. FieldMap properties Property Explanation inputFieldCount The number of defined input fields. joinDelimiter A string value used to separate input values from the same table if the output field type is string and the mergeRule is Join. mergeRule Defines how values from two or more fields from the same input table are merged into a single output value. Valid choices are as follows: First: The first input value is used. Last: The last input value is used. Join: Merge the values together using the delimiter value to separate the values (only valid if the output field type is text. Min: The smallest input value is used (only valid if the output field type is numeric. Max: The largest input value is used (only valid if the output field type is numeric). Mean: The mean is calculated using the input values (only valid if the output field type is numeric). Median: The median is calculated using the input values (only valid if the output field type is numeric). Sum: The sum is calculated using the input values (only valid if the output field type is numeric). StdDev: The standard deviation is calculated using the input values (only valid if the output field type is numeric). Count: The number of values included in statistical calculations. This counts each value except null values. outputField The properties of the output field are either set or returned in a field object. FieldMap methods Method Explanation addInputField(table_dataset, Adds a field to the list of input fields by specifying the field_name, {start_position}, name, including the path to the field's input table or {end_position}) feature class and the name of the field, as well as the start and end position of the field value, if the input value is from a text field. findInputFieldIndex (table_dataset, Returns the index position of a specific field within the field_name) FieldMap's list of input fields. getEndTextPosition(index) Returns the position within the input field value that will be used to end the new output value. This property is only used when the input field type is text. getInputFieldName(index) Returns the field name for a specific input field. getInputTableName(index) Returns the table name for a specific input field. getStartTextPosition(index) Returns the position within the input field value that will be used to start the new output value. This property is only used when the input field type is text. removeAll() Deletes the contents of the FieldMap's list of input fields. removeInputField(index) Removes an input field from the FieldMap's list of input fields. setEndTextPosition(index, Defines the value indicating the last character position of end_position) the input value used to define the new output value. This property is only used when the input field type is text. setStartTextPosition(index, Defines the value indicating the first character position of start_position) the input value used to define the new output value. This property is only used when the input field type is text. The FieldMappings object is a collection of FieldMap objects, and it is used as the parameter value for tools that perform field mapping, such as Merge. The easiest way to work with these objects is to first create a FieldMappings object, then initialize its FieldMap objects by adding the input feature classes or tables that are to be combined. Once all inputs are provided, the FieldMappings object will contain one FieldMap object, or output field, for each unique field name from all the inputs. This list can be modified by adding new fields, altering the properties and/or contents of an output field, or removing any unwanted output fields. FieldMappings properties Property Explanation fieldCount The number of output fields. fieldValidationWorkspace The workspace type defines the rules for attribute field naming. These rules are used when determining the output field names, which are based on the names of the input fields from the input tables or feature classes. For example, a file system workspace that contains shapefiles may only have field names with a maximum length of 10 characters. fields A list of field objects. Each field object represents the properties of each output field. FieldMappings methods Method Explanation addFieldMap(field_map) Adds a new FieldMap object that will define a new output field addTable(table_dataset) Specifies a table or feature class whose fields will be used to define the output fields exportToString() Saves the contents of the FieldMappings objects to a string value findFieldMapIndex(field_map_name) Using the name of the output field, returns the position of the FieldMap object for the field within the list of FieldMap objects that define the output fields getFieldMap(index) Returns a FieldMap object from the list of output fields using the index position of the FieldMap within that list loadFromString() Populates the contents of the FieldMappings object using a string definition of a FieldMappings object removeAll() Deletes the contents of the FieldMap list so that no output fields are defined removeFieldMap(index) Removes an output field in the list of FieldMap objects that define the output fields replaceFieldMap(index, value) Replaces an existing output field in the list of FieldMap objects that define the output fields using a new FieldMap object In the following example, a number of feature classes containing U.S. census data will be merged to form a new feature class. One of the input attributes found in all the inputs is a numeric field, STFID. This 15-digit value is a unique identifier for all census blocks for the United States. The value can be broken into four components. The first two digits provide the state code, the next three indicate the county, the following six identify the census tract, and the last four identify the census block. The value 360899912001006 represents the census block (1006) containing the State University of New York at Potsdam in upstate New York (36), within census tract 991200 of the county of St. Lawrence (089). The script sample will merge these feature classes together and also create two new fields, TRACTID and BLOCKID, because the input data only has the STFID attribute. To do this, the FieldMappings object is initialized using the addTable method to enter each input. Then the default FieldMappings object is modified by creating two new FieldMap objects, populating their properties, and adding them to the FieldMappings object. import arcpy from arcpy import env env.workspace = "C:/Data/CityBlocks.gdb" outfc = "C:/Data/CityBlocks.gdb/AllBlocks" # Each of the input Feature classes has an STFID, which is the # combination of the Tract ID and Block ID for each block. # Separate these values out from this field into two new # fields, TRACTID and BLOCKID. # # Create a fieldmappings and two new fieldmaps. # fieldmappings = arcpy.FieldMappings() fldmap_TRACTID = arcpy.FieldMap() fldmap_BLOCKID = arcpy.FieldMap() # List all the feature classes in the workspace that start with # 'block' in their name and are of polygon feature type. # fcs = arcpy.ListFeatureClasses("block*", "Polygon") # Create a value table that will hold the input feature classes to Merge # vTab = arcpy.ValueTable() for fc in fcs: # Adding a table is the fast way to load all the fields from the # input into fieldmaps held by the fieldmappings object. # fieldmappings.addTable(fc) # In this example also create two fieldmaps by 'chopping up' # an input field. Feed the chopped field into the new fieldmaps. # fldmap_TRACTID.addInputField(fc, "STFID") fldmap_BLOCKID.addInputField(fc, "STFID") # Populate the input value table with feature classes # vTab.addRow(fc) # Set the starting and ending position of the fields going into the # TractID fieldmap. This is the location in the STFID field where the # TractID falls. # for x in range(0, fldmap_TRACTID.inputFieldCount): fldmap_TRACTID.setStartTextPosition(x, 5) fldmap_TRACTID.setEndTextPosition(x, 10) # Set the Name of the Field output from this field map. # fld_TRACTID = fldmap_TRACTID.outputField fld_TRACTID.name = "TRACTID" fldmap_TRACTID.outputField = fld_TRACTID # Set the starting and ending position of the fields going into the # BlockID fieldmap. This is the location in the STFID field where the # blockID falls. # for x in range(0, fldmap_BLOCKID.inputFieldCount): fldmap_BLOCKID.setStartTextPosition(x, 11) fldmap_BLOCKID.setEndTextPosition(x, 16) # Set the Name of the Field output from this field map. # fld_BLOCKID = fldmap_BLOCKID.outputField fld_BLOCKID.name = "BLOCKID" fldmap_BLOCKID.outputField = fld_BLOCKID # Add the custom fieldmaps into the fieldmappings object. # fieldmappings.addFieldMap(fldmap_TRACTID) fieldmappings.addFieldMap(fldmap_BLOCKID) # Run the Merge tool. # arcpy.Merge_management(vTab, outfc, fieldmappings) The next example shows how to modify a FieldMap object after it has been created using the addTable method of the FieldMappings object. This is important when the inputs have fields with different names but logically contain the same values. import arcpy outfc = "C:/data/CityData.gdb/AllBlocks" # Want to merge these two feature classes together. Have a field # that has the same content but the names are slightly different: # Blocks1 has TRACT2000 and Blocks2 TRACTCODE. Name the output # the same as Blocks1. # fc1 = "C:/data/CityData.gdb/Blocks1" fc2 = "C:/data/CityData.gdb/Blocks2" # Create a new fieldmappings and add the two input feature classes. # fieldmappings = arcpy.FieldMappings() fieldmappings.addTable(fc1) fieldmappings.addTable(fc2) # First get the TRACT2000 fieldmap. Then add the TRACTCODE field # from Blocks2 as an input field. Then replace the fieldmap within # the fieldmappings object. # fieldmap = fieldmappings.getFieldMap(fieldmappings.findFieldMapIndex("TRACT2000")) fieldmap.addInputField(fc2, "TRACTCODE") fieldmappings.replaceFieldMap(fieldmappings.findFieldMapIndex("TRACT2000"), fieldmap) # Remove the TRACTCODE fieldmap. # fieldmappings.removeFieldMap(fieldmappings.findFieldMapIndex("TRACTCODE")) # Create a value table that will hold the inputs for Merge. # vTab = arcpy.ValueTable() vTab.addRow(fc1) vTab.addRow(fc2) # Run the Merge tool. # arcpy.Merge_management(vTab, outfc, fieldmappings) Related Topics FieldMap FieldMappings Using the field mapping control Scheduling a Python script to run at prescribed times Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Working with sets of data in Python How to schedule a geoprocessing script to run at prescribed times Scheduled Tasks Steps: 1. The method to schedule a script depends on your system. For Windows XP: a. Click the Windows Start menu, point to Control Panel, then double-click Scheduled Tasks. b. If the control panel is in category view, click Performance and Maintenance and click Scheduled Tasks. For Windows 2000 and NT: a. Click the Windows Start menu, point to Settings, point to Control Panel, then click Scheduled Tasks. For Windows Vista: a. Click the Windows Start menu, click Settings, point to Control Panel, then click System and Maintenance. Click Administrative Tools and click Schedule tasks. 2. Double-click Add Scheduled Task. 3. Complete the options on the wizard. a. When asked to click the program you want Windows to run, click the Browse button and the Python script. If the program you want to run is a Python script with arguments For more information about scheduled tasks, see the Windows Help. Steps: 1. On the last pane of Schedule Task Wizard, check the Open advanced properties check box. 2. On the Task Properties dialog box, change Run to contain the Python executable, your script, and the arguments you want the script to run, as shown in the following example. c:\python26\python.exe c:\gisWork\myscript.py c:\gisWork\gdb.mdb\counties 10 Describing data Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python Geoprocessing tools work with all types of data, such as geodatabase feature classes, shapefiles, rasters, tables, topologies, and networks. Each piece of data has particular properties that can be accessed and used to control the flow of a script or used as the parameters of a tool. For example, the output feature type of the Intersect tool is dependent on the shape type of the data being intersected— point, line, or polygon. When the Intersect tool is run within a script on a list of input datasets, you must be able to determine the shape types of the input datasets so the correct output shape type can be set. You can use the Describe function to determine the shape types of all the input datasets. Using the Describe function, a dataset's properties can be determined and used to make decisions. For instance, in the following example, the script uses Describe to evaluate the shape type (polyline, polygon, point, and so on) of input data and determine which geoprocessing tool is appropriate. import arcpy inFC = arcpy.GetParameterAsText(0) outFC = arcpy.GetParameterAsText(1) # Describe a feature class # desc = arcpy.Describe(inFC) # Get the shape type (Polygon, Polyline) of the feature class # type = desc.shapeType # If the shapeType is Polygon convert the data to polylines using the FeatureToLine tool, # otherwise just copy the data using the CopyFeatures tool. # if type == "Polygon": arcpy.FeatureToLine_management(inFC, outFC) else: arcpy.CopyFeatures_management(inFC, outFC) The Describe function returns a Describe object, with multiple properties, such as data type, fields, indexes, and many others. Its properties are dynamic, meaning that depending on what data type is described, different describe properties will be available for use. Describe properties are organized into a series of property groups. Any particular dataset will acquire the properties of at least one of these groups. For instance, if describing a geodatabase feature class, you could access properties from the GDB FeatureClass, FeatureClass, Table, and Dataset property groups. All data, regardless of the data type, will always acquire the generic Describe Object properties. Describe Object PropertiesArcInfo Item PropertiesArcInfo Table PropertiesCAD Drawing Dataset PropertiesCAD FeatureClass PropertiesCoverage FeatureClass PropertiesCoverage PropertiesDataset PropertiesdBase Table PropertiesFeatureClass PropertiesFile PropertiesFolder PropertiesGDB FeatureClass PropertiesGDB Table PropertiesGeometric Network PropertiesLayer PropertiesMap Document PropertiesMosaic Dataset PropertiesNetwork Analyst Layer PropertiesNetwork Dataset PropertiesPrj File PropertiesRaster Band PropertiesRaster Catalog PropertiesRaster Dataset PropertiesRelationshipClass PropertiesRepresentationClass PropertiesSchematic Dataset PropertiesSchematic Diagram PropertiesSchematic Folder PropertiesSDC FeatureClass PropertiesShapefile FeatureClass PropertiesTable PropertiesTableView PropertiesText File PropertiesTin PropertiesTool PropertiesToolbox PropertiesTopology PropertiesVPF Coverage PropertiesVPF FeatureClass PropertiesVPF Table PropertiesWorkspace Properties Working with property sets Some properties are members of a Property set. For example, the tolerances of a coverage or the connection properties of a workspace are returned as Property sets. Property sets have named properties that can be called from the property set itself. In the example below, the tolerances of a coverage (Fuzzy, Dangle, TicMatch, Edit, NodeSnap, Weed, Grain, and Snap) are printed to the standard output: import arcpy # Create a describe object from a coverage feature class # desc = arcpy.Describe("D:/St_Johns/covs/freshwater") # Create a property set of coverage tolerances # covTols = desc.tolerances # Print each coverage tolerance # print covTols.fuzzy print covTols.dangle print covTols.ticMatch print covTols.edit print covTols.nodeSnap print covTols.weed print covTols.grain print covTols.snap Property sets are typically used when the properties of the object being described vary. The connection properties (server, instance, database, user, and version) of an enterprise geodatabase workspace vary depending on the type of ArcSDE database that is being used, so it is well suited to a property set that has no predefined set of values. Related Topics Describe Using fields and indexes Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python When described, feature classes and tables have a fields property that returns a Python list of field objects, and an indexes property that returns a Python list of index objects. Each field or index object has a number of properties that can be used to explore the object. Alternatively, the ListFields and ListIndexes functions can be used to create the same lists. The following example shows how to create a field list and loop through the contents to find a specific field. import arcpy fc = "D:/St_Johns/data.gdb/roads" # Describe a feature class # desc = arcpy.Describe(fc) # Get a list of field objects from the describe object # fields = desc.fields for field in fields: # Check the field name, perform a calculation when finding the field 'Flag' # if field.name == "Flag": # Set the value for the field and exit loop # arcpy.CalculateField_management(fc, "Flag", "1") break The properties of the field and index objects are listed below: Property Explanation Name The name of the field. AliasName The alias name of the field. Domain The name of the associated domain. Editable True if the field is editable. IsNullable True if the field is nullable. Required True if the field is required. Length The field's length. Type SmallInteger, Integer, Single, Double, String, Date, OID, Geometry, BLOB. Scale The field's scale. Precision The field's precision. Field properties Property Explanation Name The name of the index. IsAscending True if the index is sorted in ascending order. IsUnique True if the index is unique. Fields A Python list of field objects. This is the same as using Describe's field property. Index properties Tip: ListFields and ListIndexes can be used to limit the results based on name and type. Related Topics ListFields ListIndexes Listing data Using the spatial reference class Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python Geographic datasets, such as feature classes, coverages, and rasters, have a spatial reference that defines a dataset's coordinate system, x,y domain, m-domain, and z-domain. Each part of the spatial reference has a number of properties, especially the coordinate system, which defines what map projection options are used to define horizontal coordinates. All this information is available from the spatial reference property, which is actually another object containing a number of properties. import arcpy # Describe a feature class # fc = "D:/St_Johns/data.gdb/roads" desc = arcpy.Describe(fc) # Get the spatial reference # sr = desc.spatialReference # Check if the feature class is in projected space # if sr.type == "Projected": arcpy.Copy_management(fc,"D:/St_Johns/data.gdb/roads_UTM") Creating a spatial reference using a projection (.prj) file It is not often practical to keep all details of a spatial reference inside a Python script. By using a projection file as an argument to the SpatialReference class, you can quickly complete the properties of a spatial reference and use the object as input to a geoprocessing tool. In the following example, the spatial reference is constructed using a projection file supplied as an input argument. import arcpy inputWorkspace = "c:/temp" outputName = "rivers.shp" # Get the input workspace, the output name for the new feature class # and path to an input projection file # inputWorkspace = arcpy.GetParameterAsText(0) outputName = arcpy.GetParameterAsText(1) prjFile = arcpy.GetParameterAsText(2) # Use the the projection file as input to the SpatialReference class # spatialRef = arcpy.SpatialReference(prjFile) # Use the SpatialReference object to create a new feature class with a # specific coordinate system # arcpy.CreateFeatureClass_management(inputWorkspace, outputName, "POLYLINE", "", "", "", spatialRef) Note: For a full list of properties and methods, see SpatialReference class. Note: Spatial references are sometimes referred to as Projection Engine strings. The Projection Engine (PE) is a library of code that all of ArcGIS uses for defining map projections and transforming from one projection to another. Related Topics SpatialReference How to use feature sets and record sets Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python FeatureSet objects are lightweight representations of a feature class. They are a special data element that contains not only schema (geometry type, fields, spatial reference) but also the data, including the geometry itself. RecordSet objects are similar but comparable to a table. When used in a script tool, feature sets and record sets can be used to interactively define features and records. Note: Server tools communicate using feature sets and record sets, meaning data must be created using or loaded into these objects when using server tools. The FeatureSet and RecordSet classes have the same two methods. Property Explanation load Import a feature class into the FeatureSet object. save Export to a geodatabase feature class or shapefile. FeatureSet class Property Explanation load Import a feature class into the RecordSet object. save Export to a geodatabase table or dBASE file. RecordSet class Creating and using FeatureSet and RecordSet objects FeatureSet and RecordSet objects can be created in a number of ways depending on need and application. The load method can be used to add new features or rows to the object, and the save method can be used to preserve the features or rows on disk. In addition, the input feature class or table can also be supplied as argument to the class. Both FeatureSet and RecordSet objects can also be used directly as input to a geoprocessing tool. Create an empty feature set. import arcpy # Create an empty FeatureSet object # featSet = arcpy.FeatureSet() Construct a feature set from an input feature class import arcpy # Construct a FeatureSet from a feature class # featSet = arcpy.FeatureSet("c:/base/roads.shp") GetParameterValue function If you want to create a feature set or record set with the specific schema of a tool's input, use GetParameterValue() to create an empty FeatureSet or RecordSet object with the appropriate schema. import arcpy # Add a custom server toolbox # arcpy.ImportToolbox("http://flame7/arcgis/services;BufferByVal", "servertools") # Get the default input from a tool # inRecSet = arcpy.GetParameterValue("bufferpoints", 0) Learn more about the GetParameterValue function Using the GetParameter function When working with script tools, FeatureSet and RecordSet objects can be acquired from the tool using the GetParameter function. import arcpy # Get the RecordSet from a script tool # inRecSet = arcpy.GetParameter(0) Learn more about the GetParameter function Result class' getInput/getOutput methods When using a server tool, you must explicitly ask for its output. When the output is a feature set or record set, the Result class' getOutput() method can be used to return the tool's output in a FeatureSet or RecordSet object. As well, the Result object's getInput method can be used to get an input FeatureSet or RecordSet object. Learn more about getting results from a geoprocessing tool import arcpy import time # Add a toolbox from a server # arcpy.ImportToolbox("http://flame7/arcgis/services;GP/BufferByVal", "servertools") # Use GetParameterValue to get a featureset object with the default schema of the # first parameter of the tool 'bufferpoints' # inFeatureSet = arcpy.GetParameterValue("bufferpoints", 0) # Load a shapefile into the featureset # inFeatureSet.load("c:/base/roads.shp") # Run a server tool named BufferPoints with featureset created above # result = arcpy.BufferPoints_servertools(inFeatureSet, "5 feet") # Check the status of the result object every 0.2 seconds until it has a value # of 4 (succeeded) or greater # while result.status < 4: time.sleep(0.2) # Get the output FeatureSet back from the server and save to a local geodatabase # outFeatSet = result.getOutput(0) outFeatSet.save("c:/temp/base.gdb/towers_buffer") Learn more about the Result class Example: Loading data to a feature set using cursors and an in-memory feature class import arcpy from arcpy import env env.overwriteOutput = True arcpy.ImportToolbox("http://flame7/arcgis/services;BufferByVal", "server") # List of coordinates # coordinateL = ["-117.196717216;34.046944853","-117.186226483;34.046498438",\ "-117.179530271;34.038016569","-117.187454122;34.039132605",\ "-117.177744614;34.056765964","-117.156205131;34.064466609",\ "-117.145491191;34.068261129","-117.170825195;34.073618099",\ "-117.186784501;34.068149525","-117.158325598;34.03489167"] # Create an in_memory feature class to initially contain the coordinate pairs # fc = arcpy.CreateFeatureClass_management("in_memory", "tempfc", "POINT") # Open an insert cursor # cur = arcpy.InsertCursor(fc) pointArray = arcpy.Array() pnt = arcpy.Point() # Iterate through list of coordinates and add to cursor # for coords in coordinateL: x,y = coords.split(';') pnt.ID = coordinateL.index(coords) + 1 pnt.X = x pnt.Y = y feat = cur.newRow() feat.shape = pnt cur.InsertRow(feat) pointArray.add(pnt) # Delete the cursor del cur # Create a FeatureSet object and load in_memory feature class # featSet = arcpy.FeatureSet() featSet.load(fc) results = arcpy.BufferPoints_servertools(featSet) Related Topics A quick tour of using Feature Set and Record Set Checking for the existence of data Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python To check for the existence of data in a script, use the Exists function. Exists(dataset) Tests for the existence of feature classes, tables, datasets, shapefiles, workspaces, layers, and other files in the current workspace at the time of execution. The function returns a Boolean indicating whether the element exists. Exists function When checking for the existence of geographic data, you must use the Exists function, since it recognizes catalog paths. A catalog path is a pathname that only ArcGIS recognizes. For example: D:\Data\Final\Infrastructure.gdb\EastValley\powerlines refers to the powerlines feature class found in the EastValley feature dataset in the file geodatabase Infrastructure. This is not a valid system path as far as the Windows operating system is concerned, since Infrastructure.gdb (a folder) does not contain a file named Infrastructure. In short, Windows doesn't know about feature datasets or feature classes, so you cannot use Python existence functions like os.path.exists. Of course, everything in ArcGIS knows how to deal with catalog paths. UNC (Universal Naming Convention) paths can also be used. import arcpy from arcpy import env env.workspace = "d:/St_Johns/data.gdb" fc = "roads" # Clip a roads feature class if it exists # if arcpy.Exists(fc): arcpy.Clip_analysis(fc,"urban_area","urban_roads") Tip: The Exists function honors the geoprocessing workspace environment allowing you to just specify the base name. If the data resides in an enterprise geodatabase, the name must be fully qualified. import arcpy from arcpy import env env.workspace = "Database Connections/Bluestar.sde" fc = "ORASPATIAL.Rivers" # Confirm that the feature class exists # if arcpy.Exists(fc): print "Verified %s exists" % fc In scripting, the default behavior for all tools is to not overwrite any output that already exists. This behavior can be changed by setting the overwriteOutput property to True (arcpy.env.overwriteOutput = True). Attempting to overwrite when the overwriteOutput is False will cause a tool to fail. Related Topics Exists Paths explained: Absolute, relative, UNC, and URL Setting paths to data in Python Accessing data using cursors Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python A cursor is a data access object that can be used to either iterate over the set of rows in a table or insert new rows into a table. Cursors have three forms: search, insert, or update. Cursors are commonly used to read existing geometries and write new geometries. Each type of cursor is created by a corresponding ArcPy function (SearchCursor, InsertCursor, or UpdateCursor) on a table, table view, feature class, or feature layer. A search cursor can be used to retrieve rows. An update cursor can be used to positionally update and delete rows, while an insert cursor is used to insert rows into a table or feature class. Cursor Explanation InsertCursor(dataset, {spatial_reference}) Inserts rows SearchCursor(dataset, {where_clause}, {spatial_reference}, {fields}, Read-only access {sort_fields}) UpdateCursor(dataset, {where_clause}, {spatial_reference}, {fields}, Updates or deletes {sort_fields}) rows Cursor functions Caution: All updates or insertions to a table are done outside an edit session in ArcGIS. Changes made are permanent and cannot be undone. Note: Cursors honor layer/table view definition queries and selections. The cursor object only contains the rows that would be used by any geoprocessing tool during an operation. All three cursor functions create a cursor object that can be used to access row objects. The methods supported by the row object depend on the type of cursor created. Cursors can only be navigated in a forward direction; they do not support backing up and retrieving rows that have already been retrieved or making multiple passes over data. If a script needs to make multiple passes over the data, the application must reexecute the cursor function. If both executions are made within the same edit session (or database transaction with the appropriate level of isolation), the application is guaranteed not to see any changes made to the data by other concurrently executing applications. Search or update cursors are able to be iterated with a For loop or in a While loop using the cursor's next method to return the next row. When using the next method on a cursor to retrieve all rows in a table containing N rows, the script must make N calls to next. A call to next after the last row in the result set has been retrieved returns None, which is a Python data type that acts here as a placeholder. This example shows a simple cursor operation. It prints out name and value of each string field for each row in a feature class. import arcpy fc = "D:/st_johns/roads.shp" # Create a search cursor # rows = arcpy.SearchCursor(fc) # Create a list of string fields fields = arcpy.ListFields(fc, "", "String") for row in rows: for field in fields: if field.type != "Geometry": print "%s: Value = %s" % (field.name, row.getValue(field.name)) All row objects retrieved from a table logically contain the same ordered set of fields. In particular, the order of fields in a row of a table is the same as the order of fields returned by the ListFields function. The row will only contain the visible fields of the table used to create the cursor, with each field name being a property of the object. The cursor object SearchCursor, UpdateCursor, and InsertCursor functions create a cursor object (sometimes referred to as an enumeration object) that can be used to iterate through the records. The methods of the cursor object created by the various cursor functions vary depending on the type of cursor created. The following chart shows the methods supported for each cursor type: Cursor type Method Effect on position Search next Retrieves the next row object Insert newRow Creates an empty row object insertRow Inserts a row object into the table next Retrieves the next row object updateRow Updates the current row with a modified row object deleteRow Removes the row from the table next Retrieves the next row object Update insertRow The insert cursor is used to create new rows and insert them. The basic flow of processing is to use the newRow method on the cursor object in which rows are to be inserted. This new row object contains all the fields found on the table, and you can assign values to the fields on the row before inserting the row using insertRow. import arcpy # Create insert cursor for table # rows = arcpy.InsertCursor("D:/St_Johns/data.gdb/roads_lut") x = 1 # Create 25 new rows. Set the initial row ID and distance values # while x <= 25: row = rows.newRow() row.rowid = x row.distance = 100 rows.insertRow(row) x = x + 1 updateRow The updateRow method is used to update the row at the current position of an update cursor. After fetching a row object from the cursor object, you modify the row as needed and call updateRow, passing in the modified row. import arcpy # Create update cursor for feature class # rows = arcpy.UpdateCursor("D:/St_Johns/data.gdb/roads") for row in rows: # Update the field used in buffer so the distance is based on the road # type. Road type is either 1, 2, 3, or 4. Distance is in meters. # row.buffer_distance = row.road_type * 100 rows.updateRow(row) deleteRow The deleteRow method is used to delete the row at the current position of an update cursor. After fetching the row object, you call deleteRow on the cursor to delete the row. import arcpy # Create update cursor for feature class # rows = arcpy.UpdateCursor("D:/St_Johns/data.gdb/roads") for row in rows: # Delete all rows that have a roads type of 4 if row.road_type == 4: rows.deleteRow(row) getValue and setValue There are two basic ways to get and set field values on a row: Using the field name, as in value = row.road_type Using getValue and setValue, as in value = row.getValue("road_type") Method Explanation getValue(field_name) Gets the field value isNull(field_name) Is the field value null setNull(field_name) Sets the field value to null setValue(field_name, object) Sets field value Row methods The sample below creates a lookup table for all polygon feature classes in a workspace. The lookup table contains an ID that corresponds to the ObjectID for each feature in the feature class and a distance value that could be used for the Buffer tool. import arcpy from arcpy import env import os env.overwriteOutput = 1 env.workspace = arcpy.GetParameterAsText(0) # List the polygon feature classes # fcs = arcpy.ListFeatureClasses("*","polygon") # Loop through the results. # for fc in fcs: # Get the ObjectID field # desc = arcpy.Describe(env.workspace + os.sep + fc) OIDFieldName = desc.OIDFieldName # Create lookup table name # if fc.endswith(".shp"): tab = fc.replace(".", "_lut.") else: tab = fc + "_lut" # Create lookup table and add fields # arcpy.CreateTable_management(env.workspace, tab) arcpy.AddField_management(tab,"id","long") arcpy.AddField_management(tab,"dist","long") # Open insert cursor on new lookup table # tabcur = arcpy.InsertCursor(env.workspace + os.sep + tab) # Open search cursor on feature class # featcur = arcpy.SearchCursor(env.workspace + os.sep + fc) # Loop through the rows in the feature class # for f_row in featcur: # Create a new row for the lookup table and set its ID to be the # same as the feature OID and set the distance to 100. # t_row = tabcur.newRow() t_row.id = f_row.getValue(OIDFieldName) t_row.dist = 100 # Insert the row into the lookup table and get the next row # from the feature class # tabcur.insertRow(t_row) Cursors and locking Insert and update cursors honor table locks set by ArcGIS applications. Locks prevent multiple processes from changing the same table at the same time. There are two types of locks—shared and exclusive. A shared lock is applied anytime a table or dataset is accessed. Multiple shared locks can exist for a table, but no exclusive locks are permitted if a shared lock exists. Displaying a feature class in ArcMap and previewing a table in ArcCatalog are examples of when a shared lock would be applied. Exclusive locks are applied when changes are made to a table or feature class. Editing and saving a feature class in ArcMap; changing a table's schema in ArcCatalog; or using an insert cursor on a feature class in a Python IDE, such as PythonWin, are examples of when an exclusive lock is applied by ArcGIS. Update and insert cursors cannot be created for a table or feature class if an exclusive lock exists for that dataset. The UpdateCursor or InsertCursor functions fail because of an exclusive lock on the dataset. If these functions successfully create a cursor, they apply an exclusive lock on the dataset so that two scripts cannot create an update or insert cursor on the same dataset. Locks persist until the application or script releases the dataset, either by closing or releasing the cursor object explicitly. In a script, the cursor object should be deleted so the exclusive lock it placed on the dataset is released. Otherwise, all other applications or scripts could be unnecessarily prevented from accessing a dataset. The sample below shows how to open an update cursor and release it. An error handler is used to check if the UpdateCursor function fails because of another exclusive lock on the table. import arcpy # Create update cursor for feature class # try: # The variables row and rows are initially set to None, so that they # can be deleted in the finally block regardless of where (or if) # script fails. # row, rows = None, None rows = arcpy.UpdateCursor("D:/St_Johns/data.mdb/roads") # Update the field used in buffer so the distance is based on the # road type. Road type is either 1, 2, 3 or 4. Distance is in meters. # for row in rows: row.buffer_distance = row.road_type * 100 rows.updateRow(row) except: if not arcpy.GetMessages() == "": arcpy.AddMessage(arcpy.GetMessages(2)) finally: # Regardless of whether the script succeeds or not, delete # the row and cursor # if row: del row if rows: del rows An edit session in ArcMap applies a shared lock to data during the edit session. An exclusive lock is applied when edits are saved. A dataset is not editable if an exclusive lock already exists. When working in a Python editor, such as PythonWin, you may need to clean up object references to remove dataset locks set by cursors. Use the gc (garbage collection) module to control when unused objects are removed and/or explicitly delete references within your script. Related Topics Reading geometries Setting a cursor's spatial reference Working with geometry in Python Writing geometries Specifying a query in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python Structured Query Language (SQL) is a powerful language used to define one or more criteria that can consist of attributes, operators, and calculations. For example, imagine you have a table of customer data and want to find those who spent more than $50,000 with you last year and whose business type is restaurant. You would select the customers with this expression: "Sales > 50000 AND Business_type = 'Restaurant'". When a query is specified for an update or search cursor, only the records satisfying that query are returned. A SQL query represents a subset of the single table queries that can be made against a table in a SQL database using the SQL SELECT statement. The syntax used to specify the WHERE clause is the same as that of the underlying database holding the data. The example below filters the rows of a search cursor to only roads of a specific road class: import arcpy fc = "D:/St_Johns/data.mdb/roads" # Create a search cursor using an SQL expression # rows = arcpy.SearchCursor(fc, "[roadclass] = 2") for row in rows: # Print the name of the residential road # print row.name Using AddFieldDelimiters with the SQL expression The field delimiters used in a SQL expression differ depending on the format of the queried data. For instance, file geodatabases and shapefiles use double quotes (" "), personal geodatabases use square brackets ([ ]), and ArcSDE geodatabases don't use field delimiters. The AddFieldDelimiters function can take away some of the guess work in ensuring that the field delimiters used with your SQL expression are the correct ones. The following example expands on the above example to add the proper field delimiters for the SQL expression. import arcpy fc = "D:/St_Johns/data.mdb/roads" fieldname = "roadclass" # Create field name with the proper delimiters # delimitedfield = arcpy.AddFieldDelimiters(fc, fieldname) # Create a search cursor using an SQL expression # rows = arcpy.SearchCursor(fc, delimitedfield + " = 2") for row in rows: # Print the name of the residential road print row.name Related Topics Accessing data using cursors Working with geometry in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python All simple feature classes require a geometry field, typically (but not always) named Shape. The Describe function can be used to retrieve the name of geometry field from a feature class, using the shapeFieldName property. The value of the geometry field is a geometry object, and a geometry object has a number of properties that describe the feature. The example below shows how to create a geometry object for each line feature in a feature class and sum their length: Reading_geometriesWriting_geometries import arcpy inFeatures = "d:/base/data.gdb/roads" # Create search cursor # rows = arcpy.SearchCursor(inFeatures) # Calculate the total length of all roads # length = 0 shapeName = arcpy.Describe(inFeatures).shapeFieldName # For each # for row in feat = length row, tally the length of the feature rows: row.getValue(shapeName) += feat.length # Print the total length of all roads # print length Property Explanation area The area of a polygon; empty for all other feature types centroid The true centroid if it is within or on the feature; otherwise, returns the label point (returns a point object) extent Returns an extent object firstPoint The first coordinate of the feature; returns a point object hullRectangle The coordinate pairs of the convex hull rectangle isMultipart True, if the number of parts for this geometry is more than one labelPoint The point at which the label is located; returns a point object (The labelPoint is always located within or on a feature. lastPoint The last coordinate of the feature; returns a point object length The length of the linear feature; empty for point, multipoint feature types partCount The number of geometry parts for the feature pointCount The number of point objects for the current part of geometry trueCentroid The center of gravity for a feature; returns a point object type Polygon, polyline, point, multipoint, multipatch, dimension, annotation Geometry properties Method Explanation getPart({index}) Returns an array of point objects for a particular part of geometry or an array containing a number of arrays, one for each part Geometry methods Related Topics Accessing data using cursors Reading geometries Specifying a query in Python Writing geometries Reading geometries Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python Each feature in a feature class contains a set of points defining the vertices of a polygon or line or a single coordinate defining a point feature. These points can be accessed using the geometry object, which returns them in an array of point objects. Property Explanation count The number of objects in the array. Array properties Method Explanation add(value) Adds an Array or Point object to the array in the last position. append(value) Appends an object to the array in the last position. clone(point_object) Clone the point object. extend(items) Extend the array by appending elements. getObject(index) Returns a specific object from the array. insert(index, value) Adds an object to the array in a specific position. next() Returns the next object in the array. remove(index) Removes a specific object from the array. removeAll() Removes all objects and creates an empty array. replace(index, Replaces an object by index position. value) reset() Resets the array to the first object. Note: Reset is used only for non cursor Arrays. Using reset on a cursor Array will not reset to the first record. Array methods Features in a geodatabase or shapefile can have multiple parts. The geometry object's partCount property returns the number of parts for a feature. The getPart method returns an array of point objects for a particular part of the geometry if an index is specified. If an index is not specified, an array containing an array of point objects for each geometry part is returned. Point features return a single point object instead of an array of point objects. All other feature types— polygon, polyline, and multipoint—return an array of point objects or, if the feature has multiple parts, an array containing multiple arrays of point objects. Property Explanation ID The shape ID of the point X The horizontal coordinate of the point Y The vertical coordinate of the point Z The elevation value of the point M The measure value of the point Point properties If a polygon contains holes, it will consist of a number of rings. The array of point objects returned for a polygon contains the points for the exterior ring and all inner rings. The exterior ring is always returned first, followed by inner rings, with null point objects as the separator between rings. Whenever a script is reading coordinates for polygons in a geodatabase or shapefile, it should contain logic for handling inner rings if this information is required by the script; otherwise, only the exterior ring is read. A multipart feature is composed of more than one physical part but only references one set of attributes in the database. For example, in a layer of states, the state of Hawaii could be considered a multipart feature. Although composed of many islands, it would be recorded in the database as one feature. A ring is a closed path that defines a two-dimensional area. A valid ring consists of a valid path, such that the from and to points of the ring have the same x,y coordinates. A clockwise ring is an exterior ring, and a counterclockwise ring defines an interior ring. Learn more about writing geometries The examples below will print the coordinates for all features: Reading point geometries Search cursor on a point feature class import arcpy infc = arcpy.GetParameterAsText(0) # Identify the geometry field # desc = arcpy.Describe(infc) shapefieldname = desc.ShapeFieldName # Create search cursor # rows = arcpy.SearchCursor(infc) # Enter for loop for each feature/row # for row in rows: # Create the geometry object 'feat' # feat = row.getValue(shapefieldname) pnt = feat.getPart() # Print x,y coordinates of current point # print pnt.X, pnt.Y With the above feature class, the script will return the information below: 2.0 4.0 8.0 10.0 7.0 5.0 Reading multipoint geometries Search cursor on a multipoint feature class import arcpy infc = arcpy.GetParameterAsText(0) # Identify the geometry field # desc = arcpy.Describe(infc) shapefieldname = desc.ShapeFieldName # Create search cursor # rows = arcpy.SearchCursor(infc) # Enter for loop for each feature/row # for row in rows: # Create the geometry object # feat = row.getValue(shapefieldname) # Print the current multipoint's ID # print "Feature %i:" % row.getValue(desc.OIDFieldName) # For each point in the multipoint feature, # print the x,y coordinates for pnt in feat: print pnt.X, pnt.Y With the feature class above, the script will return the information below: Feature 0: 3.0 8.0 4.0 4.0 6.0 6.0 Feature 1: 5.0 9.0 8.0 10.0 Feature 2: 9.0 5.0 Reading polyline or polygon geometries Search cursor on a polygon or line feature class import arcpy infc = arcpy.GetParameterAsText(0) # Identify the geometry field # desc = arcpy.Describe(infc) shapefieldname = desc.ShapeFieldName # Create search cursor # rows = arcpy.SearchCursor(infc) # Enter for loop for each feature/row # for row in rows: # Create the geometry object # feat = row.getValue(shapefieldname) # Print the current multipoint's ID # print "Feature %i:" % row.getValue(desc.OIDFieldName) partnum = 0 # Step through each part of the feature # for part in feat: # Print the part number # print "Part %i:" % partnum # Step through each vertex in the feature # for pnt in feat.getPart(partnum): if pnt: # Print x,y coordinates of current point # print pnt.X, pnt.Y else: # If pnt is None, this represents an interior ring # print "Interior Ring:" partnum += 1 With the feature class above, the script will return the information below. Feature 0 is a single-part polygon, feature 1 is a two-part polygon, and feature 2 is a single-part polygon with an interior ring. Feature 0: Part 0: 3.0 8.0 1.0 8.0 2.0 10.0 3.0 8.0 Feature 1: Part 0: 5.0 3.0 3.0 3.0 3.0 5.0 5.0 3.0 Part 1: 7.0 5.0 5.0 5.0 5.0 7.0 7.0 5.0 Feature 2: Part 0: 9.0 11.0 9.0 8.0 6.0 8.0 6.0 11.0 9.0 11.0 Interior Ring: 7.0 10.0 7.0 9.0 8.0 9.0 8.0 10.0 7.0 10.0 Related Topics Accessing data using cursors Specifying a query in Python Using geometry objects with geoprocessing tools Working with geometry in Python Writing geometries Writing geometries Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python Using insert and update cursors, scripts can create new features in a feature class or update existing ones. A script can define a feature by creating a point object, populating its properties, and placing it in an array. That array can then be used to set a feature's geometry. A single geometry part is defined by an array of points, so a multipart feature can be created from multiple arrays of points. Below is an example of a file to be processed by the script that follows. It contains a point ID and an xand y-coordinate. 1;-61845879.0968;45047635.4861 1;-3976119.96791;46073695.0451 1;1154177.8272;-25134838.3511 1;-62051091.0086;-26160897.9101 2;17365918.8598;44431999.7507 2;39939229.1582;45252847.3979 2;41170500.6291;27194199.1591 2;17981554.5952;27809834.8945 3;15519011.6535;11598093.8619 3;52046731.9547;13034577.2446 3;52867579.6019;-16105514.2317 3;17160706.948;-16515938.0553 The following example shows how to read a text file containing a series of linear coordinates (as above) and use them to create a new feature class. # Create a new line feature class using a text file of coordinates. # Each coordinate entry is semicolon delimited in the format of ID;X;Y # Import ArcPy and other required modules # import arcpy from arcpy import env import fileinput import string import os env.overwriteOutput = True # Get the coordinate ASCII file # infile = arcpy.GetParameterAsText(0) # Get the output feature class # fcname = arcpy.GetParameterAsText(1) # Get the template feature class # template = arcpy.GetParameterAsText(2) try: # Create the output feature class # arcpy.CreateFeatureclass_management(os.path.dirname(fcname), os.path.basename(fcname), "Polyline", template) # Open an insert cursor for the new feature class # cur = arcpy.InsertCursor(fcname) # Create an array and point object needed to create features # lineArray = arcpy.Array() pnt = arcpy.Point() # Initialize a variable for keeping track of a feature's ID. # ID = -1 for line in fileinput.input(infile): # Open the input file # set the point's ID, X and Y properties # pnt.ID, pnt.X, pnt.Y = string.split(line,";") print pnt.ID, pnt.X, pnt.Y if ID == -1: ID = pnt.ID # Add the point to the feature's array of points # If the ID has changed, create a new feature # if ID != pnt.ID: # Create a new row or feature, in the feature class # feat = cur.newRow() # Set the geometry of the new feature to the array of points # feat.shape = lineArray # Insert the feature # cur.insertRow(feat) lineArray.removeAll() lineArray.add(pnt) ID = pnt.ID # Add the last feature # feat = cur.newRow() feat.shape = lineArray cur.insertRow(feat) lineArray.removeAll() fileinput.close() del cur except Exception as e: print e.message An array of points is not necessary when writing point features. A single point object is used to set the geometry of a point feature. All geometries are validated before they are written to a feature class. Issues such as incorrect ring orientation and self-intersecting polygons, among others, are corrected when the geometry is simplified before its insertion. Example: Using SearchCursor and InsertCursor to create square buffers In some cases, it is desirable to create new geometries based on the features of another feature class. This can be achieved by using SearchCursor and InsertCursor simultaneously. In the following example, InsertCursor is used to identify x,y coordinates of an input point feature class. These point coordinates are used to calculate the corner locations for square buffer polygons that are entered into the output using InsertCursor. import arcpy from arcpy import env import os env.overwriteOutput = True # Get arguments: # Input point feature class # Output polygon feature class # Buffer distance # Boolean type: Maintain fields and field values of the input in the output # inPoints outPolys bufDist keepFields = = = = arcpy.GetParameterAsText(0) arcpy.GetParameterAsText(1) arcpy.GetParameterAsText(2) arcpy.GetParameterAsText(3) # Prepare the output based on whether field and field values are desired in the output # if keepFields: # Create empty output polygon feature class that includes fields of the input # arcpy.CreateFeatureClass(os.path.dirname(outPolys), os.path.basename(outPolys), "POLYGON", inPoints, "", "", inPoints) # Create a short list of fields to ignore when moving fields values from # input to output # ignoreFields = [] # Use Describe properties to identify the shapeFieldName and OIDFieldName # desc = arcpy.Describe(inPoints) ignoreFields.append(desc.shapeFieldName) ignoreFields.append(desc.OIDFieldName) # Create a list of fields to use when moving field values from input to output # fields = arcpy.ListFields(inPoints) fieldList = [] for field in fields: if field.name not in ignoreFields: fieldList.append(field.name) else: # Create empty output polygon feature class without fields of the input # arcpy.CreateFeatureClass(os.path.dirname(outPolys), os.path.basename(outPolys), "POLYGON", "", "", "", inPoints) # Open searchcursor # inRows = arcpy.SearchCursor(inPoints) # Open insertcursor # outRows = arcpy.InsertCursor(outPolys) # Create point and array objects # pntObj = arcpy.Point() arrayObj = arcpy.Array() for inRow in inRows: # One output feature for each input point feature inShape = inRow.shape pnt = inShape.getPart(0) # Need 5 vertices for square buffer: upper right, upper left, lower left, # lower right, upper right. Add and subtract distance from coordinates of # input point as appropriate. for vertex in [0,1,2,3,4]: pntObj.ID = vertex if vertex in [0,3,4]: pntObj.X = pnt.X + bufDist else: pntObj.X = pnt.X - bufDist if vertex in [0,1,5]: pntObj.Y = pnt.Y + bufDist else: pntObj.Y = pnt.Y - bufDist arrayObj.add(pntObj) # Create new row for output feature # feat = outRows.newRow() # Shift attributes from input to output # if keepFields: for fieldName in fieldList: feat.setValue(fieldName, inRow.getValue(fieldName)) # Assign array of points to output feature # feat.shape = arrayObj # Insert the feature # outRows.insertRow(feat) # Clear array of points # arrayObj.removeAll() # Delete inputcursor # del outRows Note: Using only geoprocessing tools, a square buffer can also be calculated using the Buffer and FeatureEnvelopeToPolygon tools in succession. Related Topics Accessing data using cursors Reading geometries Specifying a query in Python Using geometry objects with geoprocessing tools Working with geometry in Python Setting a cursor's spatial reference Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python The spatial reference for a feature class describes its coordinate system, its spatial domain, and its precision. The coordinate system is analogous to a map projection (for example, geographic, universal transverse Mercator [UTM], and state plane). It defines the mathematical relationship between the stored coordinates and actual location on the earth. The spatial domain is best described as the allowable coordinate range for x,y coordinates, m (measure)-values, and z-values. The resolution describes the number of system units per unit of measure. By default, the spatial reference of the geometry returned from a search cursor is the same as the feature class opened by the cursor. You can also set the spatial reference on an update or insert cursor. When you set the spatial reference on an update or insert cursor, you are declaring the spatial reference of the geometries you are going to write with the cursor. For example, suppose you're going to insert geometries into a feature class that is in UTM coordinates. You're going to read geometries from a text file that contains state plane coordinates and insert them into this feature class. The spatial reference of the feature class (UTM) is different than the geometries you are going to read from the text file (state plane). When you open the insert cursor on the feature class, you set its spatial reference to state plane, declaring that you want the geometries you're inserting to be converted from state plane to UTM. Therefore, the only time you need to set the spatial reference of an insert or update cursor is when the geometries you are writing are in a different spatial reference than the cursor's feature class. In the case of a search cursor, specifying a spatial reference different from the spatial reference of the cursor's feature class results in geometries that are transformed to the cursor's spatial reference. The example below has a point feature class with a coordinate system of UTM zone 21 north, defined in its spatial reference. The script will produce a text file with the coordinates of the points in decimal degrees. import arcpy # Describe a feature class with a geographic coordinate system # desc = arcpy.Describe("d:/base/data.gdb/latlongbnd") # Create search cursor. Use the spatial reference object from the # described feature class so geometries are returned in decimal degrees. # rows = arcpy.SearchCursor("d:/base/data.gdb/buildings", "", desc.spatialReference) # Open the file for output. This also creates the file if it does not exist. # out = open(arcpy.GetParameterAsText(0), "w") # Print the coordinates of each building point feature # for row in rows: # Create the geometry object # feat = row.shape # Get the geometry's point object. # pnt = feat.getPart() # Write the x,y coordinate to the output file # out.write(pnt.X + ";" + pnt.Y + "\n") # Close the output file # out.close() Related Topics Accessing data using cursors Reading geometries Specifying a query in Python Working with geometry in Python Writing geometries Using geometry objects with geoprocessing tools Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python In many geoprocessing workflows, you may need to run a specific operation using coordinate and geometry information but don't necessarily want to go through the process of creating a new (temporary) feature class, populating the feature class with cursors, using the feature class, then deleting the temporary feature class. Geometry objects can be used instead for both input and output to make geoprocessing simpler. Geometry objects can be created from scratch using Geometry, Multipoint, PointGeometry, Polygon, or Polyline classes. Using geometry as input The following sample creates a polygon geometry object created using a list of x,y coordinates. The Clip tool is then used to clip a feature class with the polygon geometry object. import arcpy # Create an Array object. # array = arcpy.Array() # List of coordinates. # coordList = ['1.0;1.0','1.0;10.0','10.0;10.0','10.0;1.0'] # For each coordinate set, create a point object and add the x- and # y-coordinates to the point object, then add the point object # to the array object. # for coordPair in coordList: x, y = coordPair.split(";") pnt = arcpy.Point(x,y) array.add(pnt) # Add in the first point of the array again to close the polygon boundary # array.add(array.getObject(0)) # Create a polygon geometry object using the array object # boundaryPolygon = arcpy.Polygon(array) # Use the geometry to clip an input feature class # arcpy.Clip_analysis("c:/data/rivers.shp", boundaryPolygon, "c:/data/rivers_clipped.shp") Outputting geometry objects Output geometry objects can be created by setting the output of a geoprocessing tool to an empty geometry object. When a tool is run when set to an empty geometry object, the tool returns a list of geometry objects. In the following example, the Copy Features tool is used to return a list of geometry objects, which can then be looped through to accumulate the total length of all features. import arcpy # Create an empty Geometry object # g = arcpy.Geometry() # Run the CopyFeatures tool, setting the output to the geometry object. GeometryList # is returned as a list of geometry objects. # geometryList = arcpy.CopyFeatures_management("c:/temp/outlines.shp", g) # Walk through each geometry, totaling the length # length = 0 for geometry in geometryList: length += geometry.length print "Total length: %f" % length Related Topics Accessing data using cursors Reading geometries Specifying a query in Python Working with geometry in Python Writing geometries Working with geodatabases in Python Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python Validating table names Geodatabases use various relational database management systems (RDBMS) to maintain the many tables that comprise a geodatabase. All tables in a geodatabase must have a unique name, so a mechanism for checking whether a table name is unique is essential when creating data in a geodatabase. Ensuring that a new table name is unique is key to removing the potential for accidentally overwriting data if the script doesn't ensure that the new output name is unique. Note: The Exists() function can check to see whether the table name is unique for a given workspace. Using the ValidateTableName() function, a script can determine whether a specific name is valid and unique to a specific workspace. The ValidateTableName() function does not determine that the specified name is unique to the specified workspace. It only returns a valid table name for that workspace. Function Explanation ValidateTableName(name, Takes a table name and a workspace path and returns a {workspace}) valid table name for the workspace ValidateTableName function Specifying the workspace as a parameter allows ArcPy to check all the existing table names and determine whether there are naming restrictions imposed by the output workspace. If the output workspace is an RDBMS, it may have reserved words that may not be used in a table name. It may also have invalid characters that cannot be used in a table or field name. All invalid characters are replaced with an underscore (_). ValidateTableName() returns a string representing a valid table name that may be the same as the input name if the input name is valid. The example below guarantees that the new output feature class created by the Copy Features tool has a unique name that is valid in any geodatabase: # Move all shapefiles from a folder into a geodatabase # import arcpy from arcpy import env # Set the workspace. List all of the shapefiles # env.workspace = "D:/St_Johns" fcs = arcpy.ListFeatureClasses("*") # Set the workspace to SDE for ValidateTableName # env.workspace = "Database Connections/Bluestar.sde" # For each feature class name # for fc in fcs: # Validate the output name so it is valid # outfc = arcpy.ValidateTableName(fc) # Copy the features from the workspace to a geodatabase # arcpy.CopyFeatures_management(fc, outfc) Validating field names Each database can have naming restrictions for field names in a table. Objects such as feature classes or relationship classes are stored as tables in an RDBMS, so these restrictions affect more than just stand-alone tables. These restrictions may or may not be common among various database systems, so scripts should check all new field names to ensure that a tool does not fail during execution. Function Explanation ValidateFieldName(name, Takes a string (field name) and a workspace path and returns {workspace}) a valid field name based on name restrictions in the output geodatabase ValidateFieldName function The example below ensures that a field is added, regardless of the input name, using the ValidateFieldName function: # Create a new numeric field containing the ratio of polygon area to # polygon perimeter. Two arguments, a feature class and field name, # are expected. # Define a pair of simple exceptions for error handling # class ShapeError(Exception): pass class FieldError(Exception): pass import arcpy import os try: # Get the input feature class and make sure it contains polygons # input = arcpy.GetParameterAsText(0) desc = arcpy.Describe(input) if desc.shapeType.lower() != "polygon": raise ShapeError # Get the new field name and validate it # fieldname = arcpy.GetParameterAsText(1) fieldname = arcpy.ValidateFieldName(fieldname, os.path.dirname(input)) # Make sure shape_length and shape_area fields exist # if len(arcpy.ListFields(input,"Shape_area")) > 0 and \ len(arcpy.ListFields(input,"Shape_length")) > 0: # Add the new field and calculate the value # arcpy.AddField_management(input, fieldname, "double") arcpy.CalculateField_management(input,fieldname, "[Shape_area] / [Shape_length]") else: raise FieldError except ShapeError: print "Input does not contain polygons" except FieldError: print "Input does not contain shape area and length fields" except: print arcpy.GetMessages(2) Whenever a script is updating a dataset, such as a feature class or table, be careful to avoid situations in which the dataset is locked. If you have opened a personal or file geodatabase in ArcCatalog, a script will not be able to update any of the geodatabase's contents until it is deselected and the folder is refreshed or ArcCatalog is closed. This includes script tools. Parsing table and field names Scripts should use the ParseTableName() and ParseFieldName() functions to split the fully qualified names for a dataset or for a column in a table into its components (database, owner, table, and column). Scripts that need to be RDBMS independent should not assume that the period (.) is the delimiter used to separate the components of a fully qualified dataset name. ArcGIS applications always use fully qualified names, so if your script is being used as the source of a script tool, any feature class name, for example, must be parsed if the script needs to determine the name of the feature class without the user and database names. In the example below, the script is checking the input feature class for specific user names. The script could use the parsing functions of Python to split the qualified name, but it would then assume a specific syntax, which may change if another database type is used. ParseTableName() returns a single string with the database name, owner name, and table name separated by commas. ParseFieldName() returns the table name and the field name, also separated by commas. A script can then reliably parse the returned string, since these functions always return the same formatted string. A string in Python has a number of native methods for manipulation. In this example, the split method is used to create a Python list, using the comma as the delimiter. Function Explanation ParseFieldName(name, Parses a fully qualified field name into its components {workspace}) (database, owner name, table name, field name) depending on the workspace ParseTableName(name, Parses a table name into its components (database, owner, {workspace}) table) depending on the workspace Parse functions # Append input feature class to another feature class and update field # import arcpy from arcpy import env import sys # Get the name of the input feature class and parse it. # env.workspace = os.path.dirname(arcpy.GetParameterAsText(0)) # Split ParseTableName's returned value to determine database, owner, and # featureclass # fullname = arcpy.ParseTableName(os.path.basename(arcpy.GetParameterAsText(0))) database, owner, featureclass = fullname.split(",") # Validate the name of the feature class that will be appended to and set # the workspace using the administrator's connection # env.workspace = "Database Connections/Trans_admin.sde" appendFC = arcpy.ValidateTableName("common", "roads") try: if owner == "TJohnson": arcpy.CalculateField_management(fullname, "AppendedBy", owner) arcpy.Append_management(fullname, appendFC) elif owner == "RSmith": arcpy.CalculateField_management(fullname, "AppendedBy", owner) arcpy.Append_management(fullname, appendFC) else: arcpy.AddError("Unknown user of input feature class") except: arcpy.AddError(arcpy.GetMessages(2)) A Python list is an ordered collection of any type of object, such as strings or numbers. Lists are zero based and can be used to effectively handle arrays of values when the order of the list's contents is known. Scripts that are used as the source of script tools can make some assumptions about their input argument values. Paths to data are always fully qualified by the geoprocessing framework. Scripts that may be run outside an ArcGIS application should not make the same assumption. Related Topics A quick tour of the geodatabase Specifying a query in Python Table basics Executing SQL using an ArcSDE connection Resource Center » Professional Library » Geoprocessing » Geoprocessing with Python » Accessing geographic data in Python Sometimes when working with tables that are not versioned, it may seem easier to query a table in a database using Structured Query Language (SQL) rather than using one of the geoprocessing tools. The ArcSDESQLExecute object supports the execution of most SQL statements and will return to the user the results of those statements. The object will return a list of lists in the case where the statement returns rows from a table; for statements that do not return rows, it will return an indication of the success or failure of the statement (True for success, None for failure). Caution: ArcSDE and GDB system tables should not be altered using anything other than ArcGIS software. Corruption can occur if these system tables are edited directly using SQL. Edits on versioned data performed using SQL should only be done through multiversioned views. For geodatabases implemented in a relational database management system (DBMS) using DBMS data types and table formats, the DBMS's own SQL may be used to work with the information stored in the database. Accessing the information in a geodatabase via SQL allows external applications to access the tabular data managed by the geodatabase. These external applications may be nonspatial database applications or custom spatial applications developed in an environment other than ArcObjects. Be aware, though, that SQL access to the geodatabase bypasses geodatabase functionality, such as topology, networks, terrains, or other class or workspace extensions. It may be possible to use DBMS features such as triggers and stored procedures to maintain the relationships between tables needed for certain geodatabase functionality. However, executing SQL commands against the database without taking this extra functionality into account—for example, issuing INSERT statements to add records to a business table—will circumvent geodatabase functionality and possibly corrupt the relationships between data in your geodatabase. Before attempting to access or modify any ArcSDE or GDB objects, read all ArcSDE and geodatabase documentation about using SQL against ArcSDE or GDB objects in the DBMS. Property transactionAutoCommit The autocommit interval. This can be used to force intermediate commits after a specified number of features have been modified. ArcSDESQLExecute properties Methods commitTransaction() No DML statements will be committed until the commitTransaction method is called. Note: A commit may also occur when the connection to ArcSDE is terminated (check specific DBMS documentation to see how each DBMS deals with a disconnect while in a transaction). execute(sql_statement) Sends the SQL statement to the database via an ArcSDE connection. If execute is run outside of a transaction, a commit will automatically take place once the SQL DML (INSERT, UPDATE, DELETE) statement has been executed. rollbackTransaction() Rollback any DML operations to the previous commit. startTransaction() To control when your changes are committed to the database, call the startTransaction method before calling execute. This starts a transaction, and no DML statements will be committed until the commitTransaction method is called. ArcSDESQLExecute methods The execute method sends the SQL statement to the database via an ArcSDE connection. If execute is run outside a transaction, a commit will automatically take place once the SQL DML (INSERT, UPDATE, DELETE) statement has been executed. ArcSDESQLExecute supports the ArcSDE Transaction model. Transactions are a property of an ArcSDE connection and bind operations so that an entire set of changes is either recorded or rejected. For example, if a set of parcels is being updated in a particular order, you can use a transaction to define the beginning and end of the changes so that all changes are posted together. If a set of changes can't be successfully inserted, the entire transaction is rejected. All transactions end when a user disconnects. ArcSDESQLExecute uses the provided ArcSDE API functions to start, commit, and rollback transactions. If you want to control when your changes are committed to the database, call the startTransaction method before calling execute. This starts a transaction, and no DML statements will be committed until the commitTransaction method is called. A commit may also occur when the connection to ArcSDE is terminated (check specific DBMS documentation to see how each DBMS deals with a disconnect while in a transaction). Within a transaction, it is also possible to rollback any DML operations to the previous commit. An autocommit interval property, transactionAutoCommit, is available. This can be used to force intermediate commits after a specified number of features have been modified. See your specific DBMS SQL Reference guide for help writing SQL statements. Examples Execute a list of SQL statements import arcpy from arcpy import env import sys try: # Make data path relative # env.workspace = sys.path[0] # Two ways to create the object, which also creates the connection to ArcSDE. # Using the first method, pass a set of strings containing the connection properties: # <serverName>,<portNumber>,<version>,<userName>,<password> # sdeConn = arcpy.ArcSDESQLExecute("gpserver3","5151","#","toolbox","toolbox") # Using the second method pass the path to a valid ArcSDE connection file # sdeConn = arcpy.ArcSDESQLExecute("data\Connection to GPSERVER3.sde") # Get the SQL statements, separated by ; from a text string. # SQLStatement = arcpy.GetParameterAsText(0) SQLStatementList = SQLStatement.split(";") print "+++++++++++++++++++++++++++++++++++++++++++++\n" # For each SQL statement passed in, execute it. # for sql in SQLStatementList: print "Execute SQL Statement: " + sql try: # Pass the SQL statement to the database. # sdeReturn = sdeConn.execute(sql) except Exception, ErrorDesc: print ErrorDesc sdeReturn = False # If the return value is a list (a list of lists), display each list as a row from the # table being queried. if isinstance(sdeReturn, list): print "Number of rows returned by query: " + len(sdeReturn), "rows" for row in sdeReturn: print row print "+++++++++++++++++++++++++++++++++++++++++++++\n" else: # If the return value was not a list, the statement was most likely a DDL statment. # Check its status. if sdeReturn == True: print "SQL statement: " + sql + " ran sucessfully." print "+++++++++++++++++++++++++++++++++++++++++++++\n" else: print "SQL statement: " + sql + " FAILED." print "+++++++++++++++++++++++++++++++++++++++++++++\n" except Exception, ErrorDesc: print Exception, ErrorDesc except: print "Problem executing SQL." Conditional update using a transaction # WARNING - DO NOT USE ON VERSIONED TABLES OR FEATURE CLASSES. # DO NOT USE ON ANY ArcSDE or GDB SYSTEM TABLES. # DOING SO MAY RESULT IN DATA CORRUPTION. import arcpy from arcpy import env import sys try: # Make data path relative (not relevant unless data is moved here and paths modified) # env.workspace = sys.path[0] #Column name:value that should be in the record. # SQLvalues = {"STREET_NAM":"'EUREKA'"} #Value that is incorrect if found in the above column. # badVal = "'EREKA'" #List of tables to look in for the bad value. # tableList = ["streetaddresses_blkA","streetaddresses_blkB", "streetaddresses_blkC"] # Two ways to create the object, which also creates the connection to ArcSDE. # Using the first method, pass a set of strings containing the connection properties: # <serverName>,<portNumber>,<version>,<userName>,<password> # sdeConn = arcpy.ArcSDESQLExecute("gpserver3","5151","#","toolbox","toolbox") # Using the second method pass the path to a valid ArcSDE connection file # sdeConn = arcpy.ArcSDESQLExecute("data\Connection to GPSERVER3.sde") for tbl in tableList: print "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" for col, val in SQLvalues.items(): print "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" #Check for the incorrect value in the column for the specific rows. If the table contains the #incorrect value, correct it using the update SQL statement. # print "Analyzing table " + tbl + " for bad data: Column:" + col + " Value: " + badVal try: sql = "select OBJECTID," + col + " from " + tbl + " where " + col + " = " + badVal print "Attempt to execute SQL Statement: " + sql sdeReturn = sdeConn.execute(sql) except Exception, ErrorDesc: print ErrorDesc sdeReturn = False if isinstance(sdeReturn, list): if len(sdeReturn) > 0: print "Identified " + str(len(sdeReturn)) + " rows with incorrect data. Starting transaction for update." # Start the transaction # sdeConn.startTransaction() print "Transaction started....." # Perform the update # try: sql = "update " + tbl + " set " + col + "=" + str(val) + " where " + col + " = " + badVal print "Changing bad value: " + badVal + " to the good value: " + val + " using update statement:\n " + sql sdeReturn = sdeConn.execute(sql) except Exception, ErrorDesc: print ErrorDesc sdeReturn = False # If the update completed sucessfully, commit the changes. If not, rollback. # if sdeReturn == True: print "Update statement: \n" + sql + " ran successfully." # Commit the changes # sdeConn.commitTransaction() print "Commited Transaction" # List the changes. # try: print "Displaying updated rows for visual inspection." sql = "select OBJECTID," + col + " from " + tbl + " where " + col + " = " + val print "Executing SQL Statement: \n" + sql sdeReturn = sdeConn.execute(sql) except Exception, ErrorDesc: print ErrorDesc sdeReturn = False if isinstance(sdeReturn, list): print len(sdeReturn), "rows" for row in sdeReturn: print row print "+++++++++++++++++++++++++++++++++++++++++++++\n" else: if sdeReturn == True: print "SQL statement: \n" + sql + "\nran successfully." print "+++++++++++++++++++++++++++++++++++++++++++++\n" else: print "SQL statement: \n" + sql + "\nFAILED." print "+++++++++++++++++++++++++++++++++++++++++++++\n" print "+++++++++++++++++++++++++++++++++++++++++++++\n" else: print "SQL statement: \n" + sql + "\nFAILED. back all changes." # Rollback changes # sdeConn.rollbackTransaction() print "Rolled back any changes." print "+++++++++++++++++++++++++++++++++++++++++++++\n" else: print "No records required updating." Rolling # Disconnect and exit del sdeConn print "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" except Exception, ErrorDesc: print Exception, ErrorDesc except: print "Problem executing SQL." Related Topics ArcSDESQLExecute