Select to view content in your preferred language

Script stops unexpectedly.

867
4
Jump to solution
10-18-2013 11:12 AM
AliciaMein
Occasional Contributor
#Script that computes the Percent forsted area from a landcover raster and #county zone data.  Then finds the buffer distance required around sampling #routes, so the buffer frstd percent matches the county frstd percent.  #BufferDist attribute of the route feature class are changed to reflect the #values found by the script.  !! The BufferDist attribute will be changed. #Set environment and declare varibles # arcpy.env.overwriteOutput = True arcpy.env.workspace = "C:/CustomTools/DeerSurveyRoutes/rtsScratch.gdb"  coPath = "C:/CustomTools/DeerSurveyRoutes/RtsAnlysVectors.gdb/County" rasPath = "C:/CustomTools/DeerSurveyRoutes/RtsAnlysRasters.gdb/WVUReclass" opnFrstdRas = arcpy.Raster("C:/CustomTools/DeerSurveyRoutes/RtsAnlysRasters.gdb/WVUReclass") rasCellSz = (opnFrstdRas.meanCellHeight + opnFrstdRas.meanCellWidth) / 2 rtsPath = "C:/CustomTools/DeerSurveyRoutes/RtsAnlysVectors.gdb/SmplRts2012Edited4CountyAnalysis"  #Set environemt and create variables for County area tabulation # arcpy.CheckOutExtension("Spatial") arcpy.env.snapRaster = rasPath znFld = "CoZoneName" clsFld = "Value" outTble = "CoTbleOpenFrst"  # Tabulate area of each class in raster and set up dictionary to hold values in table. # arcpy.sa.TabulateArea(coPath,znFld,opnFrstdRas,clsFld,outTble,rasCellSz) coOFDict = dict([((r.COZONENAME, f.name), r.getValue(f.name)) for f in arcpy.ListFields(outTble) for r in arcpy.SearchCursor(outTble)]) del r, f  #Create dictionary of Rts Containing the CoZoneName, RouteID and BufferDist rtDict = dict([((r.RouteID, f.name), r.getValue(f.name)) for f in arcpy.ListFields(rtsPath) for r in arcpy.SearchCursor(rtsPath)]) del r, f  #Loop to find buffer distance of each route that will contain the same forested percent as the county  return BuffDist # buffCur = arcpy.SearchCursor(rtsPath) #row = buffCur.next()  (not needed) for row in buffCur:     buffDist = 402     frstPrcnt = 0     frstd = coOFDict[(row.getValue(znFld),'VALUE_2')]     opn = coOFDict[(row.getValue(znFld),'VALUE_1')]     nHbt = coOFDict[(row.getValue(znFld),'VALUE_0')]     lpChkVal = frstd / (frstd + opn + nHbt)     minLpChkVal = lpChkVal - (lpChkVal * .05)     maxLpChkVal = lpChkVal + (lpChkVal * .05)     x = 0      #Set up feature layer for Buffer analysis     #thisRtID = row.getValue('RouteID')     #arcpy.MakeFeatureLayer_management(rtsPath, "selectedLine", '"RouteID" = \'' + thisRtID + '\'')  (good where clause example - do not delete)      while frstPrcnt < minLpChkVal or frstPrcnt > maxLpChkVal:              arcpy.Buffer_analysis(row.shape, "lineBuffer", buffDist,"FULL","ROUND","ALL")         arcpy.sa.TabulateArea("lineBuffer","OBJECTID",rasPath,clsFld,"BufferOFTble",rasCellSz)                  rtOFDict = dict([((r.OBJECTID, f.name), r.getValue(f.name)) for f in arcpy.ListFields("BufferOFTble") for r in arcpy.SearchCursor("BufferOFTble")])         del r, f         rtFrstd = rtOFDict[(1,'VALUE_2')]         rtOpn = rtOFDict[(1,'VALUE_1')]         rtNHbt = rtOFDict[(1,'VALUE_0')]         frstPrcnt = rtFrstd / (rtFrstd + rtOpn + rtNHbt)         newBuffVal = buffDist         x += 1         if x == 30:             rtDict[(row.getValue('RouteID'), 'BufferDist')] = 1             break         buffDist = buffDist + (x * 5 * rasCellSz)     rtDict[(row.getValue('RouteID'), 'BufferDist')] = newBuffVal  #Create Cursor to iterate through rts and dictionary to update buffer distance. # updtCur = arcpy.UpdateCursor(rtsPath)  for rows in updtCur:     dist = rtDict[(rows.getValue('RouteID'), 'BufferDist')]     rows.setValue('BufferDist', dist)     updtCur.updateRow(rows) del rows, updtCur, row, buffCur


I suspect that this sort of create, delete and overwrite is not optimal.  I am learning and would appreciate understanding what is going on.
I also realize that I might be better of passing the entire feature class and working through buffering all features instead of just one, but right now I just want to understand some concepts.
I have a feature class containing only 140ish features.  I hoped this would not be to large a burden for my computer.
I developed and tested with two routes just to make sure everything was claculated and completed.  When I took the script and ran it against a file geodatabase on a network the script immediately returned :

Runtime error <type 'exceptions.NameError'>: name 'r' is not defined

This is the variable used in the dictionary to populate the key.

When I ran the script from my C again it processed fairly quickly and returned the same error after processing 130ish records.

Is Why to broad a question? 

I have already changed the end type in the buffer tool from flat to round, because the buffers where eating themselves from the inside out.  I am going to change variable r to unique values in each dict and Id will also implement error checking.  But as is, does anybody have any idea why the script doesnt recognize r?
I appreciate all the help I have recieved.  Any comments are welcome.
Thanks,
Alicia
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
T__WayneWhitley
Honored Contributor
So now you have a KEYERROR, meaning you're having problems accessing the requested key (the key doesn't exist).

This is the error printed:

rtNHbt = rtOFDict[(1,'VALUE_0')]
KeyError: (1, 'VALUE_0')

The key is of course (1, 'VALUE_0') and apparently for this case it does not exist.  Maybe this will help you:

https://wiki.python.org/moin/KeyError


You can think what could possibly cause this missing key and correct it or otherwise trap the error, or if you like have a default value returned.

Enjoy,
Wayne


So as a very brief example using a default value of 0 (zero):
>>> # dictionary of only 2 keys, 'this' and 'that': >>> dict = {'this':123, 'that':456}  >>> # looking up an exising key, 'this': >>> dict['this'] 123  >>> # setting up a var to use if a key doesn't exist, for example 0 (zero): >>> someDefaultVal = 0  >>> # using 'get' to retrieve the default assignment in the event of a missing key: >>> dict.get('theOther', someDefaultVal) 0 >>> # of course, using 'get' to retrieve an existing assignment returns the proper val: >>> dict.get('that', someDefaultVal) 456 >>> 


Notice I am not saying this is the best way to handle this - the best way is to identify and handle the error...this is only illustrating an option to 'bypass' the error and return 0.  You'd have to be careful that the other vals in your divisor are not zero or you'll introduce a new error, division by zero.

View solution in original post

0 Kudos
4 Replies
T__WayneWhitley
Honored Contributor
What happens if you take out the following line?:
del r, f

NameError exception usually refers to a var ref that is unkown, either not properly initiated or already terminated...in your case, I think it's the way you initiated that python has already 'garbage collected' it and thus you don't need to use the 'del' command.

As for further comment on the efficiency of your script, let's just see how it runs 1st....leaving the testing to you.

Enjoy,
Wayne
0 Kudos
AliciaMein
Occasional Contributor
What happens if you take out the following line?:
del r, f

NameError exception usually refers to a var ref that is unkown, either not properly initiated or already terminated...in your case, I think it's the way you initiated that python has already 'garbage collected' it and thus you don't need to use the 'del' command.

As for further comment on the efficiency of your script, let's just see how it runs 1st....leaving the testing to you.

Enjoy,
Wayne


Wayne,
Thanks for the input.  I tried to run many different ways, and consistently stops.  Then I changed my code a slightly and ran from the development environment (outside acrmap)  and recieved the following. 

Traceback (most recent call last):
  File "C:.........StepAnalysisTestCrum4.py", line 54, in <module>
    rtNHbt = rtOFDict[(1,'VALUE_0')]
KeyError: (1, 'VALUE_0')

The error was returned after looping just shy of 4000 times.  processing 76 out of 143 lines.

My new code is very similar to the intiial.
#Set environment and declare varibles
#
import arcpy
arcpy.env.overwriteOutput = True
arcpy.env.workspace = "C:/CustomTools/DeerSurveyRoutes/RtsScratch.gdb"

coPath = "C:/CustomTools/DeerSurveyRoutes/RtsAnlysVectors.gdb/County"
rasPath = "C:/CustomTools/DeerSurveyRoutes/RtsAnlysRasters.gdb/WVUReclass"
opnFrstdRas = arcpy.Raster("C:/CustomTools/DeerSurveyRoutes/RtsAnlysRasters.gdb/WVUReclass")
rasCellSz = (opnFrstdRas.meanCellHeight + opnFrstdRas.meanCellWidth) / 2
rtsPath = "C:/CustomTools/DeerSurveyRoutes/RtsAnlysVectors.gdb/SmplRts2012Edited4CountyAnalysis"

#Set environment and create variables for County area tabulation
#
arcpy.CheckOutExtension("Spatial")
arcpy.env.snapRaster = rasPath
znFld = "CoZoneName"
clsFld = "Value"
outTble = "CoTbleOpenFrst"

# Tabulate area of each class in raster and set up dictionary to hold values in table.
#
arcpy.sa.TabulateArea(coPath,znFld,opnFrstdRas,clsFld,outTble,rasCellSz)
coOFDict = dict([((coR.COZONENAME, coF.name),coR.getValue(coF.name)) for coF in arcpy.ListFields(outTble) for coR in arcpy.SearchCursor(outTble)])
del coR, coF

#Create dictionary of Rts containing the CoZoneName, RouteID and BufferDist
rtDict = dict([((rtR.RouteID, rtF.name),rtR.getValue(rtF.name)) for rtF in arcpy.ListFields(rtsPath) for rtR in arcpy.SearchCursor(rtsPath)])
del rtR, rtF

#Loop to find buffer distance of each route that will contain the same forested percent as the county  return BuffDist
#
buffCur = arcpy.SearchCursor(rtsPath)
#row = buffCur.next()
for row in buffCur:
    buffDist = row.getValue('Yds2Meters')
    frstPrcnt = 0
    frstd = coOFDict[(row.getValue(znFld),'VALUE_2')]
    opn = coOFDict[(row.getValue(znFld),'VALUE_1')]
    nHbt = coOFDict[(row.getValue(znFld),'VALUE_0')]
    lpChkVal = frstd / (frstd + opn + nHbt)
    minLpChkVal = lpChkVal - (lpChkVal * .05)
    maxLpChkVal = lpChkVal + (lpChkVal * .05)
    x = 0
    listFrstPrcnt = []

    # Run buffer and table against initial value to set up comparison for min/max values
    
    arcpy.Buffer_analysis(row.shape, "lineBuffer", buffDist,"FULL","ROUND","ALL")
    arcpy.sa.TabulateArea("lineBuffer","OBJECTID",rasPath,clsFld,"BufferOFTble",rasCellSz)
        
    rtOFDict = dict([((r.OBJECTID, f.name),r.getValue(f.name)) for f in arcpy.ListFields("BufferOFTble") for r in arcpy.SearchCursor("BufferOFTble")])
    del r, f
    
    rtFrstd = rtOFDict[(1,'VALUE_2')]
    rtOpn = rtOFDict[(1,'VALUE_1')]
    rtNHbt = rtOFDict[(1,'VALUE_0')]
    frstPrcnt = rtFrstd / (rtFrstd + rtOpn + rtNHbt)

    listVal = frstPrcnt
    listFrstPrcnt.append(listVal)
    newBuffVal = buffDist
    buffDist = 402
    
    #Set up feature layer for Buffer analysis
    #thisRtID = row.getValue('RouteID')
    #arcpy.MakeFeatureLayer_management(rtsPath, "selectedLine", '"RouteID" = \'' + thisRtID + '\'')

    while frstPrcnt < minLpChkVal or frstPrcnt > maxLpChkVal:     
        arcpy.Buffer_analysis(row.shape, "lineBuffer", buffDist,"FULL","ROUND","ALL")
        arcpy.sa.TabulateArea("lineBuffer","OBJECTID",rasPath,clsFld,"BufferOFTble",rasCellSz)
        
        rtOF2Dict = dict([((ofR.OBJECTID, ofF.name),ofR.getValue(ofF.name)) for ofF in arcpy.ListFields("BufferOFTble") for ofR in arcpy.SearchCursor("BufferOFTble")])
        
        rtFrstd = rtOF2Dict[(1,'VALUE_2')]
        rtOpn = rtOF2Dict[(1,'VALUE_1')]
        rtNHbt = rtOF2Dict[(1,'VALUE_0')]
        frstPrcnt = rtFrstd / (rtFrstd + rtOpn + rtNHbt)

        listVal = frstPrcnt
        listFrstPrcnt.append(listVal)
        newBuffVal = buffDist
        x += 1
        buffDist = 402 + (x * 5 * rasCellSz)
        if min(listFrstPrcnt) < minLpChkVal and max(listFrstPrcnt) > maxLpChkVal:
            break
    rtDict[(row.getValue('RouteID'), 'BufferDist')] = newBuffVal
    print row.getValue('RouteID')
#Create Cursor to iterate through rts and dictionary to update buffer distance.
#
updtCur = arcpy.UpdateCursor(rtsPath)

for rows in updtCur:
    dist = rtDict[(rows.getValue('RouteID'), 'BufferDist')]
    rows.setValue('BufferDist', dist)
    updtCur.updateRow(rows)
del rows, updtCur, row, buffCur, ofR, ofF
0 Kudos
T__WayneWhitley
Honored Contributor
So now you have a KEYERROR, meaning you're having problems accessing the requested key (the key doesn't exist).

This is the error printed:

rtNHbt = rtOFDict[(1,'VALUE_0')]
KeyError: (1, 'VALUE_0')

The key is of course (1, 'VALUE_0') and apparently for this case it does not exist.  Maybe this will help you:

https://wiki.python.org/moin/KeyError


You can think what could possibly cause this missing key and correct it or otherwise trap the error, or if you like have a default value returned.

Enjoy,
Wayne


So as a very brief example using a default value of 0 (zero):
>>> # dictionary of only 2 keys, 'this' and 'that': >>> dict = {'this':123, 'that':456}  >>> # looking up an exising key, 'this': >>> dict['this'] 123  >>> # setting up a var to use if a key doesn't exist, for example 0 (zero): >>> someDefaultVal = 0  >>> # using 'get' to retrieve the default assignment in the event of a missing key: >>> dict.get('theOther', someDefaultVal) 0 >>> # of course, using 'get' to retrieve an existing assignment returns the proper val: >>> dict.get('that', someDefaultVal) 456 >>> 


Notice I am not saying this is the best way to handle this - the best way is to identify and handle the error...this is only illustrating an option to 'bypass' the error and return 0.  You'd have to be careful that the other vals in your divisor are not zero or you'll introduce a new error, division by zero.
0 Kudos
AliciaMein
Occasional Contributor
So now you have a KEYERROR, meaning you're having problems accessing the requested key (the key doesn't exist).

This is the error printed:

rtNHbt = rtOFDict[(1,'VALUE_0')]
KeyError: (1, 'VALUE_0')

The key is of course (1, 'VALUE_0') and apparently for this case it does not exist.  Maybe this will help you:

https://wiki.python.org/moin/KeyError


You can think what could possibly cause this missing key and correct it or otherwise trap the error, or if you like have a default value returned.

Enjoy,
Wayne


So as a very brief example using a default value of 0 (zero):
>>> # dictionary of only 2 keys, 'this' and 'that':
>>> dict = {'this':123, 'that':456}

>>> # looking up an exising key, 'this':
>>> dict['this']
123

>>> # setting up a var to use if a key doesn't exist, for example 0 (zero):
>>> someDefaultVal = 0

>>> # using 'get' to retrieve the default assignment in the event of a missing key:
>>> dict.get('theOther', someDefaultVal)
0
>>> # of course, using 'get' to retrieve an existing assignment returns the proper val:
>>> dict.get('that', someDefaultVal)
456
>>> 


Notice I am not saying this is the best way to handle this - the best way is to identify and handle the error...this is only illustrating an option to 'bypass' the error and return 0.  You'd have to be careful that the other vals in your divisor are not zero or you'll introduce a new error, division by zero.


I think this is the answer!   I believe an odd case, Value 0 is not returned in the summary table because no 0 values were found in the buffer.  I will test this and see.
0 Kudos