Hi Everyone -
I have a code that moves values around within a FC [which is the result of an intersection] from one field to another so that I will have them all previously intersected values aligned in one single row. The code works well when I apply it to one FC at a time, but when I extend it to a List of FCs, it does not work. I've tried fixing it by playing with the indentation of the UpdateCursor lines, but it didn't work. Any idea what might be happening/missing ?
On another token, it seems to me that what I am trying to do, it could be done a lot simpler, any ideas on how to optimize it ?
Thanks much !
Gabriel
import arcpy, os
from arcpy import env
# Set environment settings
env.workspace = r"C:\GIS\Track1\1_Orig\int2"
# Set local variables
copyFields = ("PorousMed","K_1","Pity_1","Leng_m")
insertFd1 = ['PM1','K1','P1','leng_m1']
insertFd2 = ['PM2','K2','P2','leng_m2']
insertFd3 = ['PM3','K3','P3','leng_m3']
insertFd4 = ['PM4','K4','P4','leng_m4']
insertFd5 = ['PM5','K5','P5','leng_m5']
valueList = []
try:
fcList = arcpy.ListFeatureClasses("","POLYLINE")
for fc in fcList:
print fc
rows = arcpy.da.SearchCursor(fc, copyFields)
for row in rows:
valueList.append(row[0])
valueList.append(row[1])
valueList.append(row[2])
valueList.append(row[3])
cursor = arcpy.UpdateCursor(fc, insertFd1)
for row in cursor:
row.setValue("PM1",valueList[0])
row.setValue("K1",valueList[1])
row.setValue("poros1",valueList[2])
row.setValue("leng_m1",valueList[3])
cursor.updateRow(row)
del cursor, row
cursor = arcpy.UpdateCursor(fc, insertFd2)
for row in cursor:
row.setValue("PM2",valueList[4])
row.setValue("K2",valueList[5])
row.setValue("poros2",valueList[6])
row.setValue("leng_m2",valueList[7])
cursor.updateRow(row)
del cursor, row
cursor = arcpy.UpdateCursor(fc, insertFd3)
for row in cursor:
row.setValue("PM3",valueList[8])
row.setValue("K3",valueList[9])
row.setValue("poros3",valueList[10])
row.setValue("leng_m3",valueList[11])
cursor.updateRow(row)
del cursor, row
cursor = arcpy.UpdateCursor(fc, insertFd4)
for row in cursor:
row.setValue("PM4",valueList[12])
row.setValue("K4",valueList[13])
row.setValue("poros4",valueList[14])
row.setValue("leng_m4",valueList[15])
cursor.updateRow(row)
del cursor, row
cursor = arcpy.UpdateCursor(fc, insertFd5)
for row in cursor:
row.setValue("PM5",valueList[16])
row.setValue("K5",valueList[17])
row.setValue("poros5",valueList[18])
row.setValue("leng_m5",valueList[19])
cursor.updateRow(row)
del cursor, row
except:
print arcpy.GetMessages(0)
print arcpy.GetMessages(1)
print arcpy.GetMessages(2)
Solved! Go to Solution.
This code seems to get the result (assuming that I understand it now):
import arcpy, os import sys import traceback from arcpy import env # Set environment settings # env.workspace = r"C:\GIS\Track1\1_Orig\int2" env.workspace = r"C:\Forum\updateCursorsAtts\testdata" # Set local variables dct_flds = {'PorousMed': ['PM1','PM2','PM3','PM4','PM5'], 'Kcond_1': ['Kcond1','Kcond2','Kcond3','Kcond4','Kcond5'], 'Porosity_1': ['Poros1','Poros2','Poros3','Poros4','Poros5'], 'Leng_m': ['leng_m1','leng_m2','leng_m3','leng_m4','leng_m5']} # changed fieldnames corresponding to the data # PorousMed: Text # K_1= Kcond_1: Double # Pity_1=Porosity_1: Double # Leng_m: Double def_tuple = ("",0,0,0) # create list of fields from dictionary (contains all fields: input and output) flds = [] for k, lst in dct_flds.items(): flds.append(k) for fld in lst: flds.append(fld) flds_in = dct_flds.keys() try: fcList = arcpy.ListFeatureClasses("","POLYLINE") print fcList for fc in fcList: print fc # create the list from the input fields valueList = [] with arcpy.da.SearchCursor(fc, flds_in) as curs: for row in curs: valueList.append(list(row)) # correct for less than 5 elements while len(valueList) <= 5: valueList.append(def_tuple) with arcpy.da.UpdateCursor(fc, flds) as curs: for row in curs: for fld_in, lst_out in dct_flds.items(): # val_in = row[flds.index(fld_in)] for fld_out in lst_out: num = int(fld_out[-1:]) lst_vals = list(valueList[num]) row[flds.index(fld_out)] = lst_vals[flds_in.index(fld_in)] curs.updateRow(row) except Exception as e: print e tb = sys.exc_info()[2] tbinfo = traceback.format_tb(tb)[0] pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1]) msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n" print pymsg + "\n" print msgs
I'll attach the updated dataset for you to check the result.
Kind regards, Xander
At first glance, you seem to be mixing older/original cursors and the newer data access (arcpy.da) cursors. Your syntax for the update cursors seems wrong. The arcpy.da.UpdateCursor syntax is (in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause}) whereas the arcpy.UpdateCursor syntax is (dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields}). You appear to be passing your field list as a where clause to your update cursors.
Overall, I recommend switching to using all arcpy.da cursors.
Thanks Joshua for your response. I tried what you suggested but didn't solve my main problem which is the iteration of this procedure through the other FCs. Actually, when I switched everything back to the newer data access version, it didn't work at all not even for the first FC. I know it is not ideal having cursors with DA and without it, but it gives me the result I want, only that it can be replicated with the list of FCs.
thanks again,
Gabriel
Regarding your use of the older/original UpdateCursor, you are using incorrect syntax. You are getting lucky, if one wants to call it that, because there is a bug in the UpdateCursor where passing a Python list instead of a text-based where_clause causes the where_clause to be ignored. In effect, using cursor = arcpy.UpdateCursor(fc) generates the same cursor for you.
The fact that switching everything to the Data Access cursors meant the code didn't work at all, not even the first FC, is telling you something is wrong with the code even for the first FC. What exactly happened when you use arcpy.da UpdateCursors? Does it run and nothing happens? An error code is generated?
Hi Gabriel,
I tried to understand your script but it it very confusing(please don't mind). Could you explain your work process(details are important). What are your inputs and what would be your expected result.
This will help me to write a script for you.
Surya
Yeah, some explanation on the general idea would be helpful. From what I see in your code it doesn’t make much sense:
Please note that for the second feature in the featureclass (da.searchcursor) you add the values to the list, but the values from the 1st feature will still be assigned. I don’t think that is what you want to achieve, right?
Since this is all happing in the same featureclass, you could use a single da.UpdateCursor to do this (assuming that you want to assign the value from each feature input field to the output fields of the same feature. That does make sense, although I don’t see why you would want to duplicate those values 5 times in your featureclass...
Hi Xander and Surya: Thanks for your response.
The two bullets in which Xander summarized part of my code are correct. I am sorry I should have provided a better explanation on my first post. The list of values I am creating is a 5rx4c table that I can index out as follows, so that I can move values to different fields within the same FC as:
[ 0 1 2 3 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
4 5 6 7 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
8 9 10 11 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
12 13 14 15 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
16 17 18 19] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
The values in the original file, in vertical order in the input fields, are the result of intersecting a polyline against polygons, but the main goal of this code is to have a one single part polyline that includes all the information from the intersection. I need to do this for thousands of intersected polylines {FCs} and then append them all out, but that's not in the code I posted. In order to get a one single part polyline I will dissolve the FC for the output fields.
So, yes, the valueList will have to be re-created for each FC, to re-distribute the proper values within it as indicated above.
The code, as it is, does the job for the first FC but it stalls and does not move on to the next FC.
Let me know if you have further questions. Thanks a bunch for comments !
Gabriel
By stall out, what exactly do you mean? Does it stop running and hang? Does it complete but not update what you expect? Does it stop running and generate an error?
Joshua - by stall out I mean that it does not move to the next FC and locks the modified file, that is the first FC, without generating an error,
regards,
Gabriel
Since you are using a search cursor and update cursor against the FC at the same time, and the search cursor creates the first set of locks, it may be causing an issue since the update cursor will want to generate more locks. Not sure, just thinking aloud.
One thing to try, put a del rows statement at the bottom of your try statement (indented to the same level as your search cursor statement). Deleting the search cursor explicitly will more cleanly remove the locks before you move onto the next FC. In theory, reassigning the rows variable to a new search cursor object should release the locks on the earlier search cursor, but that may not be happening cleanly.