Having problems with Runtime Error: Update Cursor

2373
10
12-01-2012 12:25 PM
VictoriaPutinski
New Contributor
I am extremely new to Python, which will become evident in this post.
This script was working just fine before trying it on a new shapefile's attribute table.
No column or row names were changed.

Here is the code:
import arcpy
import sys, os, time, copy

def POIequals(r1,r2):
    pnts=0
    #samePOI
    if r1.poi_id==r2.poi_id:
        return True #If POI_ID is the same, it is assumed features are equal
    #sameAddress
    if r1.address==r2.address:
        pnts+=1
    #sameBank
    if r1.newname==r2.newname:
        pnts+=1
    #sameCity
    if r1.city==r2.city:
        pnts+=1
    #closeLoc
    if (r1.x<=r2.x+0.0005 and r1.x>=r2.x-0.0005) and (r1.y<=r2.y+0.0005 and r1.y>=r2.y-0.0005):
        pnts+=1
    if pnts >= 3: #three of the 5 tests above must pass for features to be considered equal
        return True
    else:
        return False
    

print "Starting process..."
start=time.strftime("%a, %d %b %Y %H:%M:%S")
print start+"\n"

inFC="C:\\Users\\Toir\\Documents\\My Dropbox\\EPOIDuplicatesRemoved\\ALLFIN2002_2011\\AllFin2002_2011_Montreal.dbf"

rowsWrite = arcpy.UpdateCursor(inFC)
total=int(arcpy.GetCount_management(inFC).getOutput(0))

c=0
chold=0

for rowW in rowsWrite:
    #set variables for loop:
    poi=rowW.poi_id
    year=rowW.epoi_year
    gain=True
    loss=True
    #find if point is a gain or loss (or both):
    #where="[poi_id] = '"+poi+"'"
    rowsRead = arcpy.SearchCursor(inFC) #add "___,where)" to improve speed
    for rowR in rowsRead:
        if POIequals(rowW,rowR):
            if year-1==rowR.epoi_year:
                gain=False
            if year+1==rowR.epoi_year:
                loss=False
            if not loss and not gain:
                break
    #set change variable:
    change=""
    if gain:
        change="Gain"
    if loss:
        change="Loss"
    if gain and loss:
        change="GainAndLoss"
    if not gain and not loss:
        change="None"
    rowW.change=change
    rowsWrite.updateRow(rowW)
    #end of loop tasks:
    del rowR, rowsRead
    if c==chold:
        print "  ->"+str(c)+" of "+str(total)+" features completed. ("+str(round((float(c)/float(total)*100.0),1))+"%)"
        chold+=100
    c+=1

#unlock and final message:
del rowW,rowsWrite
print "Complete!"
end=time.strftime("%a, %d %b %Y %H:%M:%S")
print "Started: "+start+"\nEnded:   "+end


Here is the error I get:

Traceback (most recent call last):
  File "C:\Users\Toir\Documents\My Dropbox\EPOIDuplicatesRemoved\ALLFIN2002_2011\findLossAndGainWorkingBroadEquals_edit.py", line 33, in <module>
    rowsWrite = arcpy.UpdateCursor(inFC)
  File "C:\Program Files\ArcGIS\Desktop10.0\arcpy\arcpy\__init__.py", line 825, in UpdateCursor
    return gp.updateCursor(*args)
  File "C:\Program Files\ArcGIS\Desktop10.0\arcpy\arcpy\geoprocessing\_base.py", line 362, in updateCursor
    self._gp.UpdateCursor(*gp_fixargs(args)))
RuntimeError: ERROR 999999: Error executing function.


Any help on this would be great, and ASAP please!
Tags (2)
0 Kudos
10 Replies
T__WayneWhitley
Frequent Contributor
Your problem is at line 33 where the update cursor is being set on your input fc -- you said you wanted to make it run on a shapefile, so you should set it to <your shapefile name>.shp.  ...not the dbf as you have it set now.

Also, it wouldn't hurt to insert more error trapping, such as checking for existence of the input file so if it fails there you would know it, maybe something like this:

inFC="C:\\Users\\Toir\\Documents\\My Dropbox\\EPOIDuplicatesRemoved\\ALLFIN2002_2011\\AllFin2002_2011_Montreal.shp"
if arcpy.Exists(inFC):
    rowsWrite = arcpy.UpdateCursor(inFC)
else:
    print 'Could not set update cursor.'
0 Kudos
VictoriaPutinski
New Contributor
Thank you for your quick reply!

I should have made it clearer before - I am working on a shapefile, but the script is searching through the shapefile's database file. The script was always working fine before. Also the file does exist, so I'm really not too sure how to fix this. I just tried both of your suggestions and nothing worked... any more thoughts? Thanks so much!
0 Kudos
T__WayneWhitley
Frequent Contributor
While it is possible to access your shapefile's dbf separately, it is not advisable and you may corrupt your shapefile.
You should be using the cursor on the .shp and arcpy will understand to use the component dbf attribute table.

If you must have a separate stand-alone dbf table (it doesn't sound it is necessary in your case) then you can export or copy out a separate dbf table by a different name and access it with the cursor, but you will no longer have geometry access (and of course the table will no longer be associated with the shp).

I'm pretty certain this is your problem.  At any rate, the error states you cannot instantiate the cursor object.  Probably not it, but also check for schema locks.  Are you having any other errors?

EDIT:  Also, it doesn't make sense to have both an update cursor and search cursor on the same table...I see further into your code this is attempted.
0 Kudos
VictoriaPutinski
New Contributor
Okay, I actually did manage to get it working on the shapefile I need by changing ".dbf" to ".shp". It's just strange that before the script was running fine with ".dbf" I never knew the shapefile could be corrupted by doing that - I'm learning, thanks you two!

I will look at changing the search cursor.
Thanks 😄
0 Kudos
T__WayneWhitley
Frequent Contributor
Yes, well, it can be a little confusing - think of it intuitively:  why do you think the component files of a shapefile are always accessed by ArcGIS as a 'set'?...and that generally the only time a separate dbf is recognized by ArcGIS is when it is named differently or exported from a Table View (as from the attribute table window, separately named of course)?

Here's another tip:  If you need to conditionally search for values from your table while also updating it, you should probably consider reading your shapefile into a python dictionary.  This essentially loads data into memory where you can search it repeatedly as you're iterating over rows and writing your final updates row by row.  Will likely result in a significant performance boost too.

Hope that helps, and if you would please mark this post as 'answered'.  Thanks!
0 Kudos
VictoriaPutinski
New Contributor
Thanks!

Two last things: How would I read the shapefile into python as a dictionary?
And also (and I feel really dumb asking this because it's probably really obvious but I can't find it) how do you mark a thread as answered? I'm really new to this forum.
0 Kudos
T__WayneWhitley
Frequent Contributor
If your code is performing adequately enough for your purposes at the present time, I wouldn't modify it any more.
Not to discourage you (not at all), but I'd pick a more opportune time to completely rewrite the code.  There are plenty of good resources to get you started on using python dictionaries and I can post a few links if you like...

As for marking these posts, either answered or for points, there is a 'toggle button' with 2 arrows in the right margin.  Experiment with that, you'll get it.  There is a pic at the top of the page here:
http://forums.arcgis.com/

...or, more explanation here:
http://resources.arcgis.com/en/help/forums-mvp/
0 Kudos
T__WayneWhitley
Frequent Contributor
Just for starters, it's interesting to note arcpy has several functions that return dictionaries.
Basically it's a list of key/value pairs -- extremely useful, because you can 'look up' values by a 'key' - think of the key almost as a 'field' in a table (except now we're working with a different data structure than the ArcGIS tables you are already familiar with).

The following returns a dictionary of your ArcGIS install info - see the example on how to read the vals contained:

GetInstallInfo
Resource Center » Professional Library » Geoprocessing » The ArcPy site package » Functions » Licensing and installation
http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//000v0000003s000000


EDIT:  I didn't see anything in the ArcGIS webhelp (there may be something in the ArcGIS blog, maybe to do with multiprocessing, etc.) or I don't at the moment know of any examples writing a dictionary, but I thought it would only be fair to include both reading/writing, so see this on gis.stackexchange.com:

How are people using Python data structures and classes in Arcpy?
http://gis.stackexchange.com/questions/34443/how-are-people-using-python-data-structures-and-classes...
0 Kudos
MathewCoyle
Frequent Contributor
I'll post a simple example of straight joining a list of fields. It assumes the key field is the same name in both tables.

import arcpy

key_field = # common field to join on
field_list = [# list of field names to join]

update_lyr = # table to update, usually I limit this to the key_field only
avi_view = # table to join, usually I create this with a field map limited to my field_list but it isn't necessary

# This creates a list of input fields storing the name, type and length
avi_type_dict = dict((f.name, (f.type, f.length))
    for f in arcpy.ListFields(avi_view))

# this adds all the fields in your field list and references the dict of types, lengths to make them the same
for f in avi_field_list:
    arcpy.AddField_management(
        forest_lyr, f, avi_type_dict[0], field_length=avi_type_dict[1])

# this loads all of the input rows into a dictionary
view_dict = {}
for row in arcpy.SearchCursor(avi_view):
    view_dict[row.getValue(key_field)] = dict(
        (f, row.getValue(f)) for f in field_list)

# this updates the target table
updateCursor = arcpy.UpdateCursor(update_lyr)
for row in updateCursor:
    for f in field_list:
        updateVal = view_dict[row.getValue(key_field)]
        row.setValue(f, updateVal)
    updateCursor.updateRow(row)
0 Kudos