Select to view content in your preferred language

Python if ... then Statement

4920
18
08-02-2010 09:29 PM
DaveMarkey
Regular Contributor
Hi.

I am attempting to add an If statement to my Python script. What I am wanting to do is query a field in a shapefile and if it returns true delete a different shapefile. The principle idea behind my code is; If "Region" in the Clip_Feature shapefile = 'Murray Inland' then delete the contour shapefile. My problem is I don't know how to get focus onto the the Clip_Feature shapefile.  The code I have so far is:

import sys, string, os, arcgisscripting
gp = arcgisscripting.create(9.3)

Contours = "\\\\Atlas\\data\\geodata\\state\\contour\\arc"
Crossings = "\\\\Atlas\\data\\geodata\\state\\crossings\\arc"
Contour = "Contour.shp"
Crossing = "Crossing.shp"
P_L = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines"
Clip_Feature = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature\\Clip_Feature.shp"

gp.FeatureClassToFeatureClass_conversion(Contours, P_L, Contour, "")
gp.FeatureClassToFeatureClass_conversion(Crossings, P_L, Crossing, "")

gp.workspace = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature"

if "Region_No" == 3:
gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Contour.shp")

Thanks in advance.
0 Kudos
18 Replies
ChrisMathers
Deactivated User
Could you post your current code? From what is already posted I cant see why you would fall into infinity.  If it finds 'Murray Inland' and executes the for loop or not doesnt matter. It should still exit at the end of the table when row.Next() returns None.

scursor=gp.SearchCursor(Clip_Feature)
row=scursor.Next()
while row:
    if row.GetValue("Region") == 'Murray Inland':
        for ext in [".shp",".shx",".sbn",".dbf",".prj",".sbx"]:
            os.remove("C:\\Temp\\Contour"+ext)
del scursor 
0 Kudos
RichardFairhurst
MVP Honored Contributor
I can see why it falls into infinitiy.  With a While loop on a cursor you must always make sure that before you add any other code that the last line within the while loop is the code that advances the cursor, i.e., "row=scursor.Next()".  If this line of code is not at the end of the while loop block the cursor never advances at all within the loop and the while statement never becomes false (i.e., say the first row does not meet your conditiion, but that row is the only row that ever gets evaluated and never stops being evaluated so the loop never ends)  The code below is exactly the same as all of the suggestions above but note that the "row=scursor.Next() statement has been repeated inside the while loop and therefore the cursor position now advances with each pass of the while loop.


scursor=gp.SearchCursor(Clip_Feature)
row=scursor.Next()
while row:
    if row.GetValue("Region") == 'Murray Inland':
        for ext in [".shp",".shx",".sbn",".dbf",".prj",".sbx"]:
            os.remove("C:\\Temp\\Contour"+ext)
    row=scursor.Next()
del scursor 


I cannot see any obvious connection between the trigger row value and the action being done.  But I guess if this is what you want, fine.  Also, it seem the trigger only needs to occur once, but there is no certainty that there will not be multiple rows that meet the condition.  If that is the situation, the loop should be exited after the first instance of completion of the for loop (i.e., put the exit line within the if block at the same level as the for statement prior to the row advance statement).  Not sure what Python syntax is for dropping out of a while loop (I'm an ArcObjects guy still and not up to speed on all things Python), but I am sure such a statement exists.

Rich
0 Kudos
ChrisMathers
Deactivated User
To end a loop prematurly is 'break'. Thankfully in v10 we can do away with the while row: thing and go to for row in cursor: I dislike having to manually advance the cursor like that.

scursor=gp.SearchCursor(Clip_Feature)
row=scursor.Next()
while row:
    if row.GetValue("Region") == 'Murray Inland':
        for ext in [".shp",".shx",".sbn",".dbf",".prj",".sbx"]:
            os.remove("C:\\Temp\\Contour"+ext)
        break
    row=scursor.Next()
del scursor
0 Kudos
DaveMarkey
Regular Contributor
Hi.

I have finally got this script to execute successfully without error message, but only when the condition is true.  When the condition is false I get the error message shown below.  I have also include the full script.

I have kept the delete management statement as I feel this is a much more efficient method of deleting the required shapefile. As previously mentioned, it is not the delete aspect that is the problem but the fact it is not exiting the loop when the condition is false or giving an error message advising the deleted dataset does not exist when the condition is true.

Error Message:

Traceback (most recent call last):
  File "C:\Daves_Stuff\Scripts\Test.py", line 18, in <module>
    del scursor
NameError: name 'scursor' is not defined

Full Script:

import sys, string, os, arcgisscripting
gp = arcgisscripting.create(9.3)

Mooring_Structure = "Mooring_Structure.shp"
P_L = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines"
Clip_Feature = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature\\Clip_Feature.shp"
gp.FeatureClassToFeatureClass_conversion("\\\\Atlas\\data\\geodata\\statelamblands\\moor_struct\\arc", P_L, Mooring_Structure, "")

gp.workspace = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature"
scursor=gp.SearchCursor(Clip_Feature)
row=scursor.Next()
while row:
    if row.GetValue("Region") == 'North Coast':
        gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp")
        row=scursor.Next()
    del scursor
0 Kudos
RichardFairhurst
MVP Honored Contributor
You need to enclose your code in code tags (press the button that looks like "#" on the message buttons and place you code inside the tags).  Your error could occur due to not placing the code in the correct indentation level (but I cannot tell since your indentation is lost without the code tags).  I have added some exist checks that may solve the error problems.  I also believe it should be indented as follows and you should include the break statement after the deletion occurs since there is no point in processeing any more records after the shape file is deleted.:

import sys, string, os, arcgisscripting
gp = arcgisscripting.create(9.3)

Mooring_Structure = "Mooring_Structure.shp"
P_L = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines"
Clip_Feature = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature\\Clip_Feature.shp"
if gp.Exists(Clip_Feature):
  gp.FeatureClassToFeatureClass_conversion("\\\\Atlas\\data\\geodata\\statelamblands\\moor_struct\\arc ", P_L, Mooring_Structure, "")

  gp.workspace = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature"
  scursor=gp.SearchCursor(Clip_Feature)
  row=scursor.Next()
  while row:
    if row.GetValue("Region") == 'North Coast':
      if gp.Exists("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp"):
        gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp")
      break
    row=scursor.Next()
  del scursor 
0 Kudos
DaveMarkey
Regular Contributor
Thanks. I have finally got a solution that works when the condition is both true and false.  It is the �??Break�?? statement that makes this code execute successfully.  That is, exits the loop when the condition is false and prevents the shapefile does not exist error when the condition is true.  I have not used the If statement as advised prior to the shapefile creation line as to me this is not logical and the script executes successfully without this IF.  I am very surprised at the difficulty of getting a suitable solution to something as basic as an IF�?�THEN statement.  If version 10 does not need the 'Break' statement hopefully the IF...THEN statements will be easier.  Shown below is my code.

import sys, string, os, arcgisscripting
gp = arcgisscripting.create(9.3)

Mooring_Structure = "Mooring_Structure.shp"
P_L = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines"
Clip_Feature = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature\\Clip_Feature.shp"
gp.FeatureClassToFeatureClass_conversion("\\\\Atlas\\data\\geodata\\statelamblands\\moor_struct\\arc", P_L, Mooring_Structure, "")

gp.workspace = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature"
scursor=gp.SearchCursor(Clip_Feature)
row=scursor.Next()
while row:
    if row.GetValue("Region") == 'South Coast':
        gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp")
    break
row=scursor.Next()
del scursor



Now I have got this script to execute successfully I have expanded it to contain multiple true conditions and delete multiple datasets.  I am able to do this as a 'While' loop is being utilised.  My expanded script is shown below.

import sys, string, os, arcgisscripting
gp = arcgisscripting.create(9.3)

Mooring_Structure = "Mooring_Structure.shp"
P_L = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines"
Clip_Feature = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature\\Clip_Feature.shp"
gp.FeatureClassToFeatureClass_conversion("\\\\Atlas\\data\\geodata\\statelamblands\\moor_struct\\arc", P_L, Mooring_Structure, "")

gp.workspace = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature"
scursor=gp.SearchCursor(Clip_Feature)
row=scursor.Next()
while row:
    if row.GetValue("Region") == 'North Coast':
        gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp")
    if row.GetValue("Region") == 'Murray Inland':
        gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Contour.shp")
        gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp")
    if row.GetValue("Region") == 'South Coast':
        gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp")
    break
row=scursor.Next()
del scursor
0 Kudos
RichardFairhurst
MVP Honored Contributor
Your code is indented incorrectly and the way you have written your code does not process the while loop.  The way you have written it, only one row will be read and tested and then the break statement will cause the while loop to be exited (in other words, you are not processing a while loop at all, just one record of the table).  I can see why your code now avoids an error or an infinite loop, but that is because it is only considering one record and then stopping.  If the code you wrote is actually doing what you want, get rid of the while loop, because it is not being used.

To make your code run as a true While loop and process multiple tests where you could actually delete any or all of the files where you encounter matching true conditions in any of your records, you must indent the code as follows.  Also, now you must use the Exists test to avoid the possibility of attempting to delete a file multiple times and you can no longer break out of the loop.  (The break only works with a single test.  Now that you have multiple tests, a break with any of the conditions would cause only the first of the conditions encountered to cause a file deletion, but leave all of the other files untouched even if another record in the feature class would meet the conditon for deleting a different file). 

import sys, string, os, arcgisscripting
gp = arcgisscripting.create(9.3)

Mooring_Structure = "Mooring_Structure.shp"
P_L = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines"
Clip_Feature = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature\\Clip_Feature.shp"
gp.FeatureClassToFeatureClass_conversion("\\\\Atlas\\data\\geodata\\statelamblands\\moor_struct\\arc", P_L, Mooring_Structure, "")

gp.workspace = "C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Clip_Feature"
scursor=gp.SearchCursor(Clip_Feature)
row=scursor.Next()
while row:
    if row.GetValue("Region") == 'North Coast':
        if gp.Exists("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp"):
            gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp")
    if row.GetValue("Region") == 'Murray Inland':
        if gp.Exists("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Contour.shp"):
            gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Contour.shp")
        if gp.Exists("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp"):
            gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp")
    if row.GetValue("Region") == 'South Coast':
        if gp.Exists("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp"):
            gp.Delete_management("C:\\Daves_Stuff\\ArcPad_Data\\Standard_Layers\\Lamberts_Projection\\Pts_Lines\\Mooring_Structure.shp")
    row=scursor.Next() # This line must be indented one level to be inside the while loop.  If it is not, the while loop never advances the row and becomes infinte.
del scursor
0 Kudos
DaveMarkey
Regular Contributor
Hi.

Thanks for your modified code.  I am now using this.  I have now added more complexity to the IF statement by utilising 'NOT' condition.  That is, instead of evaluation if something is present, it is evaluating if something is absent.  This is shown is a subsection of my script below.  I am finding the IF statement to be quite useful.

scursor=gp.SearchCursor(Clip)
row=scursor.Next()
if row.GetValue("Region") <> 'Murray Inland':
    gp.MakeFeatureLayer("Boatmap_Index.shp", "Boatmap_Index_lyr")
del scursor
0 Kudos
RichardFairhurst
MVP Honored Contributor
Hi.

Thanks for your modified code.  I am now using this.  I have now added more complexity to the IF statement by utilising 'NOT' condition.  That is, instead of evaluation if something is present, it is evaluating if something is absent.  This is shown is a subsection of my script below.  I am finding the IF statement to be quite useful.

scursor=gp.SearchCursor(Clip)
row=scursor.Next()
if row.GetValue("Region") <> 'Murray Inland':
    gp.MakeFeatureLayer("Boatmap_Index.shp", "Boatmap_Index_lyr")
del scursor


I am glad you found my code useful and I hope it helps you understand how While loops are structured.  As far as your new code, you are again testing just one record out of what I assume could be many records.  That seems arbitrary to me.  What if the first record has a value of "Murray Inland", but the second record does not?  Wouldn't you want to create the layer then?  Or rather, wouldn't you want to create a layer file and filter out values with "Murray Inland" through a definition query?

Since I don't know how you are using this information in your model, I cannot predict exactly what behavior you are looking for.  However, normally when looking at multi-record data in combination with conditional requirements, its is rarely a simple matter of looking at one arbitrary record and making a decision based on the information contained in that one record alone.  So think this through a little bit more to make sure it really is doing what you want.
0 Kudos