Wednesday, January 5, 2011

Publishing an ArcGIS Geoprocessing Service which uses Python

The Scenario:

I have a Python script which I wish to use within a geoprocessing tool. I want to publish this tool as a geoprocessing service using ArcGIS Server.


The Problem:

In the past I've written scripts, only to struggle integrating it into a production environment. In the ArcGIS environment, this often occurs when I've finished a Model or Python Script, which works fine in ArcGIS Desktop, but not as a published Geoprocessing Service.


The Solution:

The main thing to understand is where these different technologies interact (eg. Python, ModelBuilder, ArcGIS Server). It is these interfaces between your script, your model, your toolbox and your data that must be understood.

Before I walk through the process of publishing a Python script as a GeoProcessing Service, I will highlight a few important things to consider:

Make sure all required resources are available to the ArcGISSOC user from the ArcGIS Server instance. This includes your data, SDE connection files, your scripts, network resources, etc. Anything that your script and/or model depends on must be accessible by the ArcGISSOC user from the ArcGIS Server. This can be achieved by either:
A) Sharing the resources on your network, eg. by creating a single directory for all resources; or
B) Copying the required resources to the server and updating links within the scripts and models (annoying at best).


1) Create the Python Script
Make sure you set the return parameter using the SetParameterAsText(index,value) method.

Heres an example Python script:


import arcgisscripting
import sys
import random

gp=arcgisscripting.create()

num_points=gp.GetParameterAsText(0)
ws=r"%in_memory%"
gp.Workspace=ws
myFCName=r"random_points"

gp.CreateFeatureClass_management(gp.Workspace,myFCName,"POINT")
gp.AddMessage("Feature class created")

fcDesc=gp.Describe(gp.Workspace+"/"+myFCName)

cur=gp.InsertCursor(myFCName)
pnt=gp.CreateObject("Point")

for i in range(num_points):

feature=cur.NewRow()
pnt.y=random.random()*180 - 90
pnt.x=random.random()*360 - 180
feature.shape=pnt
cur.InsertRow(feature)

del cur

myFeatureLayer=gp.MakeFeatureLayer_management(myFCFullPath,myFLName)
gp.SetParameterAsText(1,myFeatureLayer)



2) Import the script into an ArcToolbox
As far as I can tell, this process just registers a Python script with a toolbox and wraps it in a ModelBuilder Tool template. It allows the script to behave like a Tool in any other toolbox. As part of this process, you will need to specify the location of the script. This is why your script must be accessible by the ArcGISSOC user as described above. You must also, specify the input and output parameters that your script is expecting and their data types.

Example values for an output parameter:
Display Name: BufferedFeatures
Data Type: Feature Layer
Type: Derived
Direction: Output

3) Create a Geoprocessing Model using ModelBuilder.
The main thing to remember here is to use the correct input and output parameter data types. There are limitations on which data types can be exposed via the REST interface. These restrictions only apply to the input and output values of the MODEL, not the Script! Details can be found here

4) Add the registered script into the model
Drag the new Script from your Toolbox (in ArcCatalog) into the new Model. This will add the Python script into your Model and will behave like any other tool. Link the input and output parameters to the script, by opening the script within your model and selecting the parameters you created earlier.

5) Publish the Toolbox
Your toolbox can now be published to ArcGIS Server. Simply right click on the Toolbox in ArcCatalog and select "Publish to ArcGIS Server...". Select next to the prompt.


James.