Try/Except statement inside of For Loop

3677
5
Jump to solution
01-21-2014 08:47 AM
RachelAlbritton1
New Contributor III
This script is meant to loop through several records. I a problem arise with processing a record I want the tool to skip that record and loop to the next record. I was working for an error code I was getting, but now I'm getting a new error and the script no longer loops back to  process the next record. Any thoughts on what's happening?

This is only part of the script that's inside the for loop -

 import arcpy, os, shutil, datetime from arcpy import env from arcpy.sa import*  #set workspaces arcpy.env.workspace = arcpy.GetParameterAsText(0)  outputWorkspace = arcpy.GetParameterAsText(1)  arcpy.env.overwriteOutput = True  #Check out the ArcGIS 3D Analyst extension license arcpy.CheckOutExtension("3D") arcpy.CheckOutExtension("Spatial")  arcpy.SetProgressor("default","Conducting Viewshed Analysis")  #Variables ObsPts = arcpy.GetParameterAsText(2) footprint =  arcpy.GetParameterAsText(3)  Elevation = arcpy.GetParameterAsText(4) BareElevation = arcpy.GetParameterAsText(5) Ocean = arcpy.GetParameterAsText(6) FloorField = arcpy.GetParameterAsText(7)  Year = arcpy.GetParameterAsText(8)  #Set analysis extent to elevation raster arcpy.env.extent = Elevation arcpy.env.cellSize = Elevation  #Open error log file infile = open(outputWorkspace+"\\Error_Log_"+Year+".txt","w")  #Count number of parcels being processed arcpy.AddMessage("\nCalculating viewshed for "+str(RangeCount)+" parcels")  sc = arcpy.SearchCursor(PointsFL)  for row in sc:      try:               #Get Parcel ID value         value = row.ID         count = row.FID+1         FlrCnt = row.getValue(FloorField)          #Get bare earth elevation of parcel         arcpy.SetProgressorLabel("Changing elevation footprint to bare earth elevation for point "+str(value))         SQL = "Id =" +str(value)+""         arcpy.SelectLayerByAttribute_management(PointsFL,"NEW_SELECTION",SQL)         arcpy.SelectLayerByLocation_management(footprintFL,"INTERSECT",PointsFL)          arcpy.env.workspace = IntermediateFiles #need to change workspace so that the .save files get saved correctly         outExtractByMask = ExtractByMask(BareElevation,footprintFL)         outExtractByMask.save(IntermediateFiles+"\\ebm_"+str(value))          ElevAvg = ElevAvgTables+"\\avgelev_"+str(value)+".dbf"         arcpy.Statistics_analysis(outExtractByMask,ElevAvg,[["VALUE","MEAN"]])          arcpy.AddField_management(ElevAvg,"Pt_ID","SHORT")         arcpy.CalculateField_management(ElevAvg,"Pt_ID",value)         arcpy.AddJoin_management(PointsFL,"Id",ElevAvg,"Pt_ID","KEEP_COMMON")          Field1 = os.path.basename(ObsPts).split(".")[0]+".SPOT"         Field2 = "!"+os.path.basename(ElevAvg).split(".")[0]+".MEAN_VALUE!"         arcpy.CalculateField_management(PointsFL,Field1,Field2,"PYTHON_9.3")         arcpy.RemoveJoin_management(PointsFL)          #Set parcel elevation to 0 this will be replaced by SPOT value caclualted above         RastFootprint = IntermediateFiles+"\\fp_"+str(value).split(".")[0]         arcpy.PolygonToRaster_conversion(footprintFL,"FID",RastFootprint,"MAXIMUM_AREA","",6)         outIsNull = IsNull(RastFootprint) #Identify NoData Areas         outIsNull.save(IntermediateFiles+"\\null1_"+str(value))         outCon = Con(outIsNull,Elevation,0,"") #Use Con tool to change building footprint to elevation of 0 while leaving all other building footprints as is         outCon.save(IntermediateFiles+"\\con1_"+str(value)) #Final raster to be used in viewshed analysis          #buffer selected viewpoint         arcpy.SetProgressorLabel("Buffering point "+str(value))         outBuffer = IntermediateFiles+"\\buffer_"+str(value)+".shp"         arcpy.Buffer_analysis(PointsFL,outBuffer,"1 mile")          #Convert buffer polygon to line         BufferLine = IntermediateFiles+"\\BufferLine_"+str(value)+".shp"         arcpy.FeatureToLine_management(outBuffer,BufferLine)          #Clip buffer to Ocean         arcpy.SetProgressorLabel("Clipping point "+str(value)+" buffer to ocean")         BufferClip = IntermediateFiles+"\\buffer_clipped_"+str(value).split(".")[0]+".shp"         arcpy.Clip_analysis(outBuffer, Ocean, BufferClip)          if FlrCnt ==1: #parcel floor count =1             arcpy.AddMessage("\nParcel "+str(value)+" has 1 story to process. Calculating viewshed now...")             print "\nParcel ",str(value)," has 1 story to process. Calculating viewshed now..."                          DegViewshed(1,10) #Calculate the viewshed with an observer height of 10 feet then move to point              arcpy.AddMessage("First floor viewshed for parcel "+str(value)+" has been completed...")                               print "First floor viewshed for parcel ",str(value)," has been completed..."             arcpy.AddMessage(str(count)+" of "+str(RangeCount)+"parcles has been completed.\n")             print str(count)," of "+str(RangeCount)," parcels has been processed.\n"          else: #if parcel has 1.5 floors or greater do this             arcpy.AddMessage("\nParcel "+str(value)+" has 2 stories to process. Calculating viewsheds now...")             print "\nParcel ",str(value)," has 2 stories to process. Calculating viewsheds now..."             DegViewshed(1,10) #Calculate first floor view, then             arcpy.AddMessage("First floor viewshed for parcel "+str(value)+" has been completed...")             print "First floor viewshed for parcel ",str(value)," has been completed..."                                         DegViewshed(2,20) #Calculate second floor view             arcpy.AddMessage("Second floor viewshed for parcel "+str(value)+" has been completed...")                               print "Second floor viewshed for parcel ",str(value)," has been completed..."             arcpy.AddMessage("Viewsheds for "+str(count)+" of "+str(RangeCount)+" parcels have been processed.\n")             print "Viewsheds for",str(count)," of ",str(RangeCount),"parcels have been processed.\n"      except:          arcpy.AddMessage("***An error occured processing parcel "+str(value)+". Refer to error log for details.")         print "***An error occured processing parcel "+str(value)+". Refer to error log for details."         infile.write("An error occured processing parcel "+str(value)+".\n")         infile.write(arcpy.GetMessages()+"\n")         arcpy.SelectLayerByAttribute_management(PointsFL, "CLEAR_SELECTION")         arcpy.SelectLayerByLocation_management(footprintFL,"CLEAR_SELECTION")     del row     del sc          del row del sc            
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
markdenil
Occasional Contributor III
Get rid of the row and cursor object deletes just before the continue that you added.
The deletes are still inside the for loop
destroying the cursor there shoots the for loop in the foot;
it has nowhere to go.

conceptually, you have:
1. get a row
2. try something complex
3. if the try fails, write home then kill the cursor
-- and where does the next row for the loop come from???

get rid of the break and the continue too,
the loop should continue without prompting if you let it alone.
break and continue are for when there is further processing inside the loop you want to skip,
or if you want to jump out of the loop early.

just try using
except:     pass

at least just to try it out.
This should let the loop run.

View solution in original post

0 Kudos
5 Replies
JoshuaChisholm
Occasional Contributor III
Hello Rachel,

I'm a little unclear as to what's going on. You have an impressively complicated script. I'm sure you're having on hell of a time trying to debug it. Which error message are you currently getting?

I think you should get rid of "del row and del sc" from within your for loop. You have it twice. You can't delete sc when you're still looping through it. Also, the del lines outside the for loop will error out because row and sc will have already been deleted at the end of the for loop.

Judging by your code, you probably already know this, but there are two python keywords that might help you out. When you add the keyword continue python will automatically jump to the next item in the current loop. The keyword break will end the current loop and resume the script after the current loop. If you're working on loops in loops, it will only apply to the most resent loop.

Also note that everything that happens before the try fails is permanent.
For example, if all your code works up to your last print line (under try), which errors out, then your records will still be fully processed. Since there would have techically been an error, the code under except will also be run.

Hope to hear back from you soon. Good luck!
0 Kudos
RachelAlbritton1
New Contributor III
Thanks for such a quick response.

Essentially the issue is the for loop doesn't loop back to the next record if an error occurs with the current record. The script just stops. For example, I'm currently getting an Execute Error for a record (The specific error isn't my concern at the moment - the concern is the ability of the FOR LOOP to log an error and go to the next record). Rather then reporting the error to the error log then going to the next record, the script stops. I need it to keep going through all the records. I tried your suggestions, but no luck. The error is occurring within the For Loop:

   except:

        arcpy.AddMessage("***An error occured processing parcel "+str(value)+". Refer to error log for details.")
        print "***An error occured processing parcel "+str(value)+". Refer to error log for details."
        infile.write("An error occured processing parcel "+str(value)+".\n")
        infile.write(arcpy.GetMessages()+"\n")
        arcpy.SelectLayerByAttribute_management(PointsFL, "CLEAR_SELECTION")
        arcpy.SelectLayerByLocation_management(footprintFL,"CLEAR_SELECTION")
        break
    del row
    del sc
    continue
0 Kudos
JoshuaChisholm
Occasional Contributor III
Which lines is erroring out? If it's within the try method, then I'm really stumped, if it's within the except method or somewhere else in the script, then we'll need to fix it.

In terms of the continue and break lines, I think you have them in the wrong spots. That break line in the except method will break the latest for loop (skipping all records after the first error occurs).
Since the continue is at the very end of the for loop, it's useless. The code would move on to the next record anyway. I wouldn't even use continue and break at this time. My apologizes for being them up.

I'd suggest trying the script like you have it, but without the continue and break lines.

Good luck Rachel. Let me know how it goes!
0 Kudos
markdenil
Occasional Contributor III
Get rid of the row and cursor object deletes just before the continue that you added.
The deletes are still inside the for loop
destroying the cursor there shoots the for loop in the foot;
it has nowhere to go.

conceptually, you have:
1. get a row
2. try something complex
3. if the try fails, write home then kill the cursor
-- and where does the next row for the loop come from???

get rid of the break and the continue too,
the loop should continue without prompting if you let it alone.
break and continue are for when there is further processing inside the loop you want to skip,
or if you want to jump out of the loop early.

just try using
except:     pass

at least just to try it out.
This should let the loop run.
0 Kudos
RachelAlbritton1
New Contributor III
Thanks Mdenil - that worked!
0 Kudos