Problems with an Update Cursor

375
6
Jump to solution
08-24-2018 09:46 AM
JoeBorgione
MVP Esteemed Contributor

ArcGIS ArcMap 10.5.1

I'm having an issue with an update cursor that has me dead in the water.

In my script, I run a da search cursor and create a list of a specific attribute from a table:

arcpy.MakeTableView_management('MyBacteriaCounts','ba_view')

sum_table = 'BA_SampleDate_Summary'
with arcpy.da.SearchCursor(sum_table,'MySampleDate') as cursor:
    for row in cursor:
        date_list.append(row[0])

#date_list = [u'1/29/2014', u'2/27/2013', u'2/13/2013', u'1/14/2016']
‍‍‍‍‍‍

Then I step through that list and perform a selection.  The selection of course on the table view of that table created a in line 1 above:

for d in date_list:
    select = "MySampleDate = '{}'".format(d)
    arcpy.SelectLayerByAttribute_management("ba_view","NEW_SELECTION",select)

So far so good. As I step through date_ list, I need to perform calculation/update on a given field of the selected set.  That field needs to be unique and is based on a variable value concatenated with another field value with a unique identifier that is logically incremented concatenated to that:

pre = 'BA'
newdate = '20160114'
unique_id = 'XYZ'

final_value = '{} {} {}'.format(pre,newdate,unique_id)
‍‍‍

So if there are 3 records selected and they all have the same value of new date and the final_value would look like this:

BA 20160114 ABC1

BA 20160114 ABC2

BA 20160114 ABC3

The problem I'm having is getting a unique value for unique_id.  There may be several records selected that will be assigned the same value of newdate (which is just a reformat of 'd' in date_list); outside of an edit session I've tried to perform a arcpy.CalculateField_management() to the table view; that calculation is then reflected in the actual table.  The problem I have with that is the unique_id isn't so unique since I'm making the calculation to the entire selected set.

I shifted gears and tried using an arcpy.da.UpdateCursor() while in an edit session.  However, that approach has presented me with a different problem. Apparently, one cannot run and update cursor on a table view.  With the table view records selected, I apply the update cursor to the table itself, but none of the records of the table itself show as selected so my update is applied to the entire 5600 +- records.

What am I missing here? I thought when I make a selection to the table view, that selection is then reflected on the table itself, but I'm either under the wrong impression, or I'm doing something wrong.

Bottom line:  I'm looking for a way to calculate a unique value of a field for each record of a selected set.

(Dan; this relates back to my post a couple days ago to format a time stamp to milliseconds.  I was hoping to use that as my unique_id but haven't been able to get it to work for this application)

can't wait to retire....
0 Kudos
1 Solution

Accepted Solutions
DarrenWiens2
MVP Honored Contributor

Can you use the OID/FID rather than incremental number?

Alternatively, you might be able to use a timestamp like below:

import time
for i in range(0,10):
    timestamp = int(time.time()*10000000)
    cur_id = 'BA 20160114 ABC {}'.format(timestamp)
    print(cur_id)

BA 20160114 ABC 15351426652282692
BA 20160114 ABC 15351426652283268
BA 20160114 ABC 15351426652283508
BA 20160114 ABC 15351426652283718
BA 20160114 ABC 15351426652283840
BA 20160114 ABC 15351426652283930
BA 20160114 ABC 15351426652284028
BA 20160114 ABC 15351426652284128
BA 20160114 ABC 15351426652284510
BA 20160114 ABC 15351426652284910

View solution in original post

6 Replies
DarrenWiens2
MVP Honored Contributor

Can you use the OID/FID rather than incremental number?

Alternatively, you might be able to use a timestamp like below:

import time
for i in range(0,10):
    timestamp = int(time.time()*10000000)
    cur_id = 'BA 20160114 ABC {}'.format(timestamp)
    print(cur_id)

BA 20160114 ABC 15351426652282692
BA 20160114 ABC 15351426652283268
BA 20160114 ABC 15351426652283508
BA 20160114 ABC 15351426652283718
BA 20160114 ABC 15351426652283840
BA 20160114 ABC 15351426652283930
BA 20160114 ABC 15351426652284028
BA 20160114 ABC 15351426652284128
BA 20160114 ABC 15351426652284510
BA 20160114 ABC 15351426652284910

View solution in original post

JoeBorgione
MVP Esteemed Contributor

Went the route of sticking the OID on the tail end; they want the time.  I'll look closely at what you provided above, and see if I can make it stick.  Single quotes and double quotes, and {}.format() etc in  the 'expression' of the CalculateField_management() can reek havoc on an otherwise good mood!  :})

can't wait to retire....
0 Kudos
JoeBorgione
MVP Esteemed Contributor

Thanks Darren- once again you have come to my rescue!  I tweaked your code a little and came up with this:

import time
for i in range(1,10):
    int_time = int(time.time()*1000)
    str_time = str(int_time)
    mil = str_time[-4:]
    hr = str_time[:2]
    min = str_time[2:4]
    sec = str_time[4:6]
    print('{}{}{}{}'.format(hr,min,sec,mil))
    time.sleep(.25)

#putting it to sleep pretty much assures unique values:
# returns this:

1535142187
1535142439
1535142689
1535142940
1535143190
1535143441
1535143691
1535143942
1535144193 # 15 hr 35 min 14 sec 3942 millisec

it's a time stamp that is what they want!

can't wait to retire....
JoeBorgione
MVP Esteemed Contributor

time.time returns 'epoch time' for the actual time use datetime.now() and slice it up the same way:

from datetime import datetime
for i in range(1,10):
    ct = datetime.now()
    str_time = str(ct.strftime('%H%M%S%f'))
    hr = str_time[:2]
    min = str_time[2:4]
    sec = str_time[4:6]
    mil = str_time[-4:]
    print('{}{}{}{}'.format(hr,min,sec,mil))
    time.sleep(.13)

again, the time.sleep() with an odd ball fraction of a second assures uniqueness in the 'timestamp'....

can't wait to retire....
0 Kudos
JoshuaBixby
MVP Esteemed Contributor

I am glad you found a solution.  Regarding your comment, "Apparently, one cannot run and update cursor on a table view," I regularly use update cursors against feature layers and table views.  Since you didn't post the code, I can't comment specifically, but I did want to let you know that update cursors do work with table views in general.

0 Kudos
JoeBorgione
MVP Esteemed Contributor

I got a weird error pop up when ran the code with the table view itself as a update cursor parameter.  I'll try it again when get back to work and start a new thread with the details.  It seemed odd to me as well...

can't wait to retire....
0 Kudos