If else statement

6829
63
Jump to solution
08-28-2013 04:39 AM
JamesSmith7
Emerging Contributor
I am modifying a script suggested in a prior thread.  http://forums.arcgis.com/threads/90242-Polygon-Centroid?highlight=jsmith0705

I want to be able to select a line, determine if the ARCLENGTH field has a value greater than zero, return that value if greater than zero, if not return the value from the Shape_Length field.

The script runs with no errors or results. 

import arcpy  mxd = arcpy.mapping.MapDocument ("CURRENT") df = arcpy.mapping.ListDataFrames (mxd)[0]  lyr = arcpy.mapping.ListLayers(mxd, "Lot_Lines", df)[0]  for lyr in arcpy.mapping.ListLayers(mxd):  tlyr = lyr  dsc = arcpy.Describe(tlyr)  sel_set = dsc.FIDSet  if dsc.shapeType == "Line":   if len(sel_set) > 0: #If ARCLENGTH value > 0           arcpy.AddMessage(str(ARCLENGTH)) #Return ARCLENGTH value   else:    arcpy.AddMessage(str(Shape_Length)) #Return Shape_Length value
Tags (2)
0 Kudos
63 Replies
MichaelVolz
Esteemed Contributor
Have you checked to see if some of your earlier statements are getting the desired results such as the Describe?

Can you get a length of your sel_set to see if that is returning values?
0 Kudos
JamesSmith7
Emerging Contributor
Have you checked to see if some of your earlier statements are getting the desired results such as the Describe?

Can you get a length of your sel_set to see if that is returning values?


Michael,

I have used the arcpy.AddMessage.  I noticed that when the AddMessage is inserted after the variables it returns the value.  But, when I use the AddMessage after the sel_set = dsc.fidSet, the value is returned three times.  Which is odd.  I need to research why the value is returned three times.
0 Kudos
RichardFairhurst
MVP Alum
import arcpy

mxd = arcpy.mapping.MapDocument ("CURRENT")
df = arcpy.mapping.ListDataFrames (mxd)[0] 
lyr = arcpy.mapping.ListLayers(mxd, "Lot_Lines", df)[0]

for lyr in arcpy.mapping.ListLayers(mxd):
 tlyr = lyr
 dsc = arcpy.Describe(tlyr)
 sel_set = dsc.fidSet
 if dsc.shapeType == "Polyline":
  rows = arcpy.da.SearchCursor(tlyr, "OBJECTID = " + sel_set)
  for row in rows:
   arcLength = row.ARCLENGTH
   shapeLength = row.Shape_Length
  if arcLength > 0:
   print arcLength
  else:
   print shapeLength
  del row
  del rows


The error is in line 32, for row in rows: RuntimeError: An invalid SQL statement was used.  I know the select Object ID works, because it changes values depending on the feature selected.


When you switched back to the original cursor type you got no records because your where clause needs to use the IN operator not the = operator.

The error using the new arcpy.da cursor is due to the cursor declaration syntax being different.  With the arcpy data access (arcpy.da) cursor you have to supply a mandatory field name list prior to defining an optional where clause.  Your code has no field list.  At a minimum the field list would have to include OBJECTID, ARCLENGTH and Shape_Length.  So this code:

  rows = arcpy.da.SearchCursor(tlyr, "OBJECTID = " + sel_set)

should be changed to this code:

  rows = arcpy.da.SearchCursor(tlyr, ["OID@", "ARCLENGTH", "SHAPE@LENGTH"], "OBJECTID IN (" + sel_set +")")

OID@ makes sure you get the correct ObjectID field name reference, regardless of the database.  Possibly SHAPE@LENGTH should be Shape_Length, depending on whether you want to access a geodatabase length field or the actual shape geometry length.  You also do not have to use field names again after getting the cursor.  You can use numbers to represent the fields.  So that means the code beyond that line could also change to:

  rows = arcpy.da.SearchCursor(tlyr, ["OID@", "ARCLENGTH", "SHAPE@LENGTH"], "OBJECTID IN (" + sel_set + ")")
  for row in rows:
   arcLength = row.[1]
   shapeLength = row.[2]
  if arcLength > 0:
   print arcLength
  else:
   print shapeLength
  del row
  del row
0 Kudos
JamesSmith7
Emerging Contributor
Why are your rows numbered 1 and 2?  Should they be 0 and 1.  Since, python normally begins the numbering sequence with zero.

When you switched back to the original cursor type you got no records because your where clause needs to use the IN operator not the = operator.

The error using the new arcpy.da cursor is due to the cursor declaration syntax being different.  With the arcpy data access (arcpy.da) cursor you have to supply a mandatory field name list prior to defining an optional where clause.  Your code has no field list.  At a minimum the field list would have to include OBJECTID, ARCLENGTH and Shape_Length.  So this code:

  rows = arcpy.da.SearchCursor(tlyr, "OBJECTID = " + sel_set)

should be changed to this code:

  rows = arcpy.da.SearchCursor(tlyr, ["OID@", "ARCLENGTH", "SHAPE@LENGTH"], "OBJECTID IN (" + sel_set +")")

OID@ makes sure you get the correct ObjectID field name reference, regardless of the database.  Possibly SHAPE@LENGTH should be Shape_Length, depending on whether you want to access a geodatabase length field or the actual shape geometry length.  You also do not have to use field names again after getting the cursor.  You can use numbers to represent the fields.  So that means the code beyond that line could also change to:

  rows = arcpy.da.SearchCursor(tlyr, ["OID@", "ARCLENGTH", "SHAPE@LENGTH"], "OBJECTID IN (" + sel_set + ")")
  for row in rows:
   arcLength = row.[1]
   shapeLength = row.[2]
  if arcLength > 0:
   print arcLength
  else:
   print shapeLength
  del row
  del row
0 Kudos
JamesSmith7
Emerging Contributor
Thanks for the explanations, information, and suggested script. 

I want to use the Shape_Length field, which is the actual geometry length.

The script runs with added arcpy.AddMessages throughout.  Yet, the script does not print the ARCLENGTH or Shape_Length value.

When you switched back to the original cursor type you got no records because your where clause needs to use the IN operator not the = operator.

The error using the new arcpy.da cursor is due to the cursor declaration syntax being different.  With the arcpy data access (arcpy.da) cursor you have to supply a mandatory field name list prior to defining an optional where clause.  Your code has no field list.  At a minimum the field list would have to include OBJECTID, ARCLENGTH and Shape_Length.  So this code:

  rows = arcpy.da.SearchCursor(tlyr, "OBJECTID = " + sel_set)

should be changed to this code:

  rows = arcpy.da.SearchCursor(tlyr, ["OID@", "ARCLENGTH", "SHAPE@LENGTH"], "OBJECTID IN (" + sel_set +")")

OID@ makes sure you get the correct ObjectID field name reference, regardless of the database.  Possibly SHAPE@LENGTH should be Shape_Length, depending on whether you want to access a geodatabase length field or the actual shape geometry length.  You also do not have to use field names again after getting the cursor.  You can use numbers to represent the fields.  So that means the code beyond that line could also change to:

  rows = arcpy.da.SearchCursor(tlyr, ["OID@", "ARCLENGTH", "SHAPE@LENGTH"], "OBJECTID IN (" + sel_set + ")")
  for row in rows:
   arcLength = row.[1]
   shapeLength = row.[2]
  if arcLength > 0:
   print arcLength
  else:
   print shapeLength
  del row
  del row
0 Kudos
MichaelVolz
Esteemed Contributor
How many features do you have in your target feature class?

If you print out the fidset, are all of these features included in the semicolon-delimited string?

Can you post the results of printing the fidset from your dsc object?
0 Kudos
RichardFairhurst
MVP Alum
How many features do you have in your target feature class?

If you print out the fidset, are all of these features included in the semicolon-delimited string?

Can you post the results of printing the fidset from your dsc object?


If the fidset is delimited with semicolons it will have to be changed so that the fid values are delimited by commas for the where clause SQL to work.  The SQL IN operator only works with lists of values separated by commas.  Nothing in SQL works with semicolon separated lists.
0 Kudos
JamesSmith7
Emerging Contributor
How many features do you have in your target feature class?

If you print out the fidset, are all of these features included in the semicolon-delimited string?

Can you post the results of printing the fidset from your dsc object?


The feature class has over a million records. 

Printing that many records will take quite a while.

The arcpy.AddMessage("Continue") value was returned.
0 Kudos
MichaelVolz
Esteemed Contributor
James:

Can you create a feature class with a small subset of features (say 10) and then print out the fidset?

It appears from Richard's last post that the semi-colon delimited string will need to be converted to a comma separated list.  You shouldbe able to find python methods to easily perform that process.
0 Kudos
RichardFairhurst
MVP Alum
The feature class has over a million records. 

Printing that many records will take quite a while.

The arcpy.AddMessage("Continue") value was returned.


If there are a million FID values placed within the IN clause I don't know that there won't be an error.  Try it on a much smaller set first.  I suspect the cursor won't accept a string that big that it could pass to the query parser and performance would be horrible.

If it is going to process the entire table don't include a where clause.  If it is a selection based on some grouped attribute values include those fields in the field list and write a logical SQL expression that gets the selection.  If you are doing it based on a spatial query and get a huge list, perhaps try feeding portions of the OID list in a for loop to the query expression if an error gets thrown or performance drops too drastically.
0 Kudos