Field not get calculated in geoprocessing service

1519
15
Jump to solution
10-01-2013 08:57 AM
ionarawilson1
Occasional Contributor III
This script works great in ArcMap, updating the field EditField. However when I create a geoprocessing service from the result and run it, the field does not get update, although I get no error messages when running it. Does anybody would have any idea why the field would not get updated with the geoprocessing service? Thank you

# -*- coding: utf-8 -*- # --------------------------------------------------------------------------- # calcfeatures_script.py # Created on: 2013-09-30 15:22:46.00000 #   (generated by ArcGIS/ModelBuilder) # Usage: calcfeatures_script <Selecting_Features> <value>  # Description:  # test # ---------------------------------------------------------------------------  # Import arcpy module import os, sys, arcpy, traceback, arcgisscripting  # Script arguments Selecting_Features = arcpy.GetParameterAsText(0) value = arcpy.GetParameterAsText(1) Stewardship = arcpy.GetParameterAsText(2) arcpy.AddMessage("TEST") arcpy.AddMessage(value)   # Local variables: Input_Points = Stewardship #Final_Output = value  Input_Points_Layer = "SamplePoints_Layer"  # Process: Make Feature Layer arcpy.MakeFeatureLayer_management(Input_Points, Input_Points_Layer) # Process: Select Layer By Location arcpy.SelectLayerByLocation_management(Input_Points_Layer, "INTERSECT", Selecting_Features, "", "NEW_SELECTION")  # Process: Calculate Field    with arcpy.da.UpdateCursor(Input_Points_Layer, ("City")) as rows:         # row comes back as a tuple in the order specified here, so Office is row[0], Forester is row[1]         for row in rows:             row[0] = value                         rows.updateRow(row)
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
ionarawilson1
Occasional Contributor III
Ok, I found what the problem was. A parameter cannot have a feature class as an input (go figure!), so if you use arcpy.GetParameterAsText() and then have that parameter as a featureset (which I needed for my gp) it won't work. What I did was to create a variable for that parameter and when I run it inside ArcMap I grab the layer for that feature class (in my case the layer is referencing a feature class in a sde geodatabase). Then I publish the gp, then when I run the geoprocessing service I can grab the file directly from the connection instead of the layer. I hope it will help somebody because it took me a while to figure this out.

 Input_Polygons = "Stewardship"    with arcpy.da.UpdateCursor(Input_Polygons, ("DateStart", "PlanID", "FFY")) as rows:      for row in rows:          if not (row[1] or "").strip(): #covers blank, one blank space, or Null             Datestarstr1 = row[0]             Datestarstr2 = str(Datestarstr1)                      yearonly = Datestarstr2[0:4]                               row[2] = yearonly              rows.updateRow(row)    

View solution in original post

0 Kudos
15 Replies
T__WayneWhitley
Frequent Contributor
...just a shot at this, have you verified your data is accessible by Server?

Making your data accessible to ArcGIS Server
Services » ArcGIS for Server (Windows) » Publishing services » How to publish services
http://resources.arcgis.com/en/help/main/10.1/index.html#//01540000039r000000


...and have you set up the script params via the Service Editor?

Overview of geoprocessing task settings
Services » ArcGIS for Server (Windows) » Publishing services » Types of services » Geoprocessing services » Publishing geoprocessing services
http://resources.arcgis.com/en/help/main/10.1/index.html#//01540000058s000000
0 Kudos
ionarawilson1
Occasional Contributor III
Thank you Wayne. I checked everything you mentioned and everything seems fine. What I ended up doing is putting the file in a sde geodatabase and instead of asking the user to choose the file, I created a constant path to the SDE geodatabase. It worked like a charm. I am not sure why the geodatabase that is not in SDE is not being updated. I will try again with a constant path and see if that works. But I am happy it is working now, because my final goal was to edit a file in a SDE geodatabase (I thought it would be difficult so I started testing with a local file geodatabase). Thank you!

# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------------
# calcfeatures_script.py
# Created on: 2013-09-30 15:22:46.00000
#   (generated by ArcGIS/ModelBuilder)
# Usage: calcfeatures_script <Selecting_Features> <value> 
# Description: 
# test
# ---------------------------------------------------------------------------

# Import arcpy module
import os, sys, arcpy, traceback, arcgisscripting
arcpy.env.workspace = "Database Connections\\sars.sde\\"
# Script arguments
Selecting_Features = arcpy.GetParameterAsText(0)
value = arcpy.GetParameterAsText(1)




# Local variables:
Input_Points = "sars.dbo.CITYTEST"
#Final_Output = value

Input_Points_Layer = "SamplePoints_Layer"

# Process: Make Feature Layer
arcpy.MakeFeatureLayer_management(Input_Points, Input_Points_Layer)
# Process: Select Layer By Location
arcpy.SelectLayerByLocation_management(Input_Points_Layer, "INTERSECT", Selecting_Features, "", "NEW_SELECTION")

# Process: Calculate Field



with arcpy.da.UpdateCursor(Input_Points_Layer, ("City")) as rows:
        # row comes back as a tuple in the order specified here, so Office is row[0], Forester is row[1]
        for row in rows:
            row[0] = value
           
            rows.updateRow(row)


0 Kudos
ionarawilson1
Occasional Contributor III
I tried doing the same with the file geodatabase and it worked. For some reason it need to have a constant path and a workspace defined. Now it is updating perfectly 🙂

# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------------
# calcfeatures_script.py
# Created on: 2013-09-30 15:22:46.00000
#   (generated by ArcGIS/ModelBuilder)
# Usage: calcfeatures_script <Selecting_Features> <value> 
# Description: 
# test
# ---------------------------------------------------------------------------

# Import arcpy module
import os, sys, arcpy, traceback, arcgisscripting
#arcpy.env.workspace = "Database Connections\\sars.sde\\"
arcpy.env.workspace = "d:/ArcGISData/SARS/Python_10April2013/SARS.gdb"
# Script arguments
Selecting_Features = arcpy.GetParameterAsText(0)
value = arcpy.GetParameterAsText(1)




# Local variables:
#Input_Points = "sars.dbo.CITYTEST"
Input_Points = "Stewardship"
#Final_Output = value

Input_Points_Layer = "SamplePoints_Layer"

# Process: Make Feature Layer
arcpy.MakeFeatureLayer_management(Input_Points, Input_Points_Layer)
# Process: Select Layer By Location
arcpy.SelectLayerByLocation_management(Input_Points_Layer, "INTERSECT", Selecting_Features, "", "NEW_SELECTION")

# Process: Calculate Field



with arcpy.da.UpdateCursor(Input_Points_Layer, ("City")) as rows:
        # row comes back as a tuple in the order specified here, so Office is row[0], Forester is row[1]
        for row in rows:
            row[0] = value
           
            rows.updateRow(row)
0 Kudos
T__WayneWhitley
Frequent Contributor
I am experimenting with this as well....I thought this was an important find:

http://forums.arcgis.com/threads/77380-Use-feature-class-with-a-GP-service#4

...and I quote the response below from Kevin Hibma (thank you Kevin) and I thought that clever as Kevin puts it, to 'mash up paths' or to run the model/script against a layer (rather than the hard-coded path).  Finally, the database must be registered as datastore.

"...the user of the service is basically trying to remotely administer a geodatabase and the featureclasses inside: you'll have to create a sort of look up and pass just simple names to the service. In this scenario I assume you'll be working against 1 to any number of featureclasses. Here you have 2 ways to do this:
1) Accept a NAME from the user, the service then uses the name to mash up paths, find the featureclass in a geodatabase, and perform the operation. (You can do this in a model, but a script might be easier)
2) Drag all the layers that a user may want to act upon into your MXD. Run your model against a layer. Publish. Inside the Service Editor, change the parameter to choice list. Finish publishing. When the user consumes the service they pick 1 or more layers from the parameter control.

Both of these methods would require registering the database as a datastore..."


Enjoy,
Wayne
0 Kudos
ionarawilson1
Occasional Contributor III
I need to read again and again to understand this part about mashin up paths. Do  you have any examples you can show me?

Can you tell me why my example does not work with the geoprocessing service (it works in ArcMap) although, the other models worked when the input was not a parameter? Thank you!!

# Import arcpy module
import os, sys, arcpy, traceback, arcgisscripting
arcpy.env.workspace = "Database Connections\\sars.sde\\"
#arcpy.env.workspace = "d:/ArcGISData/SARS/Python_10April2013/SARS.gdb"

# Script arguments
Selecting_Features = arcpy.GetParameterAsText(0)
value = arcpy.GetParameterAsText(1)
stewardship =  arcpy.GetParameterAsText(2)

# Local variables:
#Input_Points = "sars.dbo.CITYTEST"
Input_Points = stewardship
#Final_Output = value

Input_Points_Layer = "SamplePoints_Layer"

# Process: Make Feature Layer
arcpy.MakeFeatureLayer_management(Input_Points, Input_Points_Layer)
# Process: Select Layer By Location
arcpy.SelectLayerByLocation_management(Input_Points_Layer, "INTERSECT", Selecting_Features, "", "NEW_SELECTION")

# Process: Calculate Field



# Process: Calculate Field
#arcpy.CalculateField_management(Input_Points_Layer, "City, '"' + value + '"', "PYTHON_9.3")

with arcpy.da.UpdateCursor(Input_Points_Layer, ("City")) as rows:
        # row comes back as a tuple in the order specified here, so Office is row[0], Forester is row[1]
        for row in rows:
            row[0] = value
           
            rows.updateRow(row)

0 Kudos
T__WayneWhitley
Frequent Contributor
Certainly, at the post I gave you that tereshenkov made (after Kevin's answer) that includes his 'mash-up', it looks like the below where in fact he used a kind of variable substitution to feed to the Truncate tool (the tool is irrelevant, I think you are simply passing in a text value).

r'C:\sde_at_DB_101.sde\%s' %GetPolyFC

So his text value passed in called 'GetPolyFC' (actually it is called something else initially, but he passed the val to a new variable, so it's the same thing).

The tool he is executing I suppose needs the full pathname i.e. including the workspace, which in his case is the server accessible pathname to his sde file containing the db params - that's actually the 1st part of the string above:

r'C:\sde_at_DB_101.sde'

So the so-called mash-up is a Python trick to substitute %s with the value of GetPolyFC, understand?  The text passed is the feature class name - and if the user types that in wrong, he even checks for existence and traps that error (if you look at his code).

Hope that helps.

Enjoy,
Wayne


EDIT:  So, I haven't tested this yet (I will be conducting this simple test tomorrow), but I think that would be called a 'User Defined Value', covered here:

Input modes and parameter data types
Desktop » Geoprocessing » Sharing geoprocessing workflows » Sharing workflows with geoprocessing services » Publishing geoprocessing services
http://resources.arcgis.com/en/help/main/10.1/index.html#/Input_modes_and_parameter_data_types/00570...
0 Kudos
T__WayneWhitley
Frequent Contributor
So, if this helps at all, the term 'mash-up' is just in this case a way to describe combining text to make valid pathnames...not to be confused with how the term is used to combine web services to make maps, sorry 'bout that if confusing.

This simple code illustration should help maybe:
>>> GetPolyFC = 'my user-defined value'
>>> workspace = r'\\myServer\myGDB.sde'
>>> theFullPath = workspace + r'\%s' %GetPolyFC

>>> print '"' + theFullPath + '"'
"\\myServer\myGDB.sde\my user-defined value"


 
OR MAYBE THIS, IF YOU LIKE IT BETTER:
(either way, pathnames are assembled out of text passed in)

>>> import os
>>> os.path.join(workspace, GetPolyFC)

'\\\\myServer\\myGDB.sde\\my user-defined value'
>>> 
0 Kudos
ionarawilson1
Occasional Contributor III
Thank you for sending this and for the thorough explanation. My script is in a toolbox, so I was trying to set that parameter. I tried feature set, feature class and string. What would be the type of that user defined parameter? I first tried as a feature set and got an error when trying to run the gp (of course because it goes to the memory so arcgis server can't find it. Then I tried as a feature class. The gp runs ok, but it does not upated the field. Then lastly, I tried to set it as a string, and I got a big error when trying to run the gp. So I guess I don't know how to set up a user-defined parameter. Thank you!

Traceback (most recent call last): File "D:\arcgisserver\directories\arcgissystem\arcgisinput\CalcFeaturesStewardshipParam4.GPServer\extracted\v101\python_10april2013\calcfeatures_script._forStewardship.py", line 41, in arcpy.MakeFeatureLayer_management("Database Connections\\Connection to tfsgis-iisd01IWILSON.sde\\%s" %Input_Points , Input_Points_Layer) File "c:\program files\arcgis\server\arcpy\arcpy\management.py", line 5748, in MakeFeatureLayer raise e ExecuteError: Failed to execute. Parameters are not valid. ERROR 000732: Input Features: Dataset Database Connections\Connection to tfsgis-iisd01IWILSON.sde\sars.DBO.Stewardship does not exist or is not supported Failed to execute (MakeFeatureLayer). Failed to execute (CalcFeaturesStewardship). Failed to execute (CalcFeaturesStewardship).

import os, sys, arcpy, traceback, arcgisscripting
#arcpy.env.workspace = "Database Connections\\sars.sde\\"
arcpy.env.workspace =  "Database Connections\\Connection to tfsgis-iisd01IWILSON.sde"

# Script arguments
Selecting_Features = arcpy.GetParameterAsText(0)
value = arcpy.GetParameterAsText(1)
stewardship =  arcpy.GetParameterAsText(2)




# Local variables:
#Input_Points = "sars.dbo.CITYTEST"
Input_Points = stewardship
#Final_Output = value

Input_Points_Layer = "SamplePoints_Layer"

# Process: Make Feature Layer
arcpy.MakeFeatureLayer_management("Database Connections\\Connection to tfsgis-iisd01IWILSON.sde\\%s" %Input_Points , Input_Points_Layer)
# Process: Select Layer By Location
arcpy.SelectLayerByLocation_management(Input_Points_Layer, "INTERSECT", Selecting_Features, "", "NEW_SELECTION")

# Process: Calculate Field



# Process: Calculate Field
#arcpy.CalculateField_management(Input_Points_Layer, "City, '"' + value + '"', "PYTHON_9.3")

with arcpy.da.UpdateCursor(Input_Points_Layer, ("City")) as rows:
        # row comes back as a tuple in the order specified here, so Office is row[0], Forester is row[1]
        for row in rows:
            row[0] = value
           
            rows.updateRow(row)

0 Kudos
T__WayneWhitley
Frequent Contributor
I see you're using Database Connections which likely cannot be resolved by ArcGIS Server....that is simply a connection file stored in your user directory.  Notice how in the other thread referenced, he has copied (or created another one) it to a place on the C drive of the server where it is accessible.  You can put it where you like, just your GIS Server has to be able to 'see' it...

That's the 1st thing I saw.  If you're taking the text mashup approach, you should be passing text in the tool param, and define it in the service editor as user-defined.
0 Kudos