I summarize rows in a table in the SearchCursor and store them as variables. I want to refer to these variables in the following update cursor to write to a table. I get the following error on the second last line of code (in red): Tuple object does not support item assignment. When I debug the code, ROW[0] equals 'ARSSPAN' as a string. I want ROW[0] to reference the integer ARSSPAN summarized in the search cursor above. In the next iteration of the UpdateCursor, I want the integer STSPAN to be written out, etc. I feel my issue is with assembling a variable reference through concatenating a string with the iterator. Any assistance would be greatly appreciated.
# Create the search cursor to iterate through table and sum spans and cost
with arcpy.da.SearchCursor(fcdtest, ("FeedClass","SHAPE_Length","MGMTCOST",)) as cursor:
for row in cursor:
if row[0] == "ARS":
ARSSPAN += row[1]/55
ARSCOST += row[2]
elif row[0] == "ST":
STSPAN += row[1]/55
STCOST += row[2]
elif row[0] == "S":
SSPAN += row[1]/55
SCOST += row[2]
elif row[0] == "ARU":
ARUSPAN += row[1]/55
ARUCOST += row[2]
elif row[0] == "UT":
UTSPAN += row[1]/55
UTCOST += row[2]
elif row[0] == "U":
USPAN += row[1]/55
UCOST += row[2]
fld = "YR2015"
feedcls = ["ARS","ST","S","ARU","UT","U"]
for cls in feedcls:
with arcpy.da.UpdateCursor(out_data, (fld,)) as cursor:
row[0] = cls + 'SPAN'
cursor.updateRow(row)
Solved! Go to Solution.
I see what you're doing here and it works, however I wouldn't recommend this approach as eval will run any python code, its a fairly large 'backdoor' so to speak (enables people to potentially inject malicious python code to run inside your code.. not so dangerous for a desktop script with known users, but could potentially compromise an entire organization if it was web based.)
Essentially eval is extracting the value from that concatenated string variable name by simply evaluating the variable name which returns the associated value, then assigning it to row[0].
Instead, I'd recommend instantiating a dictionary where the keys are your string keywords i.e.: "ARSSPAN" and the values are the associated int value. Then populate this dictionary in your SearchCursor loop, rather than simply assigning the variable names.
Then instead of using eval, you can use a string as the key in your dictionary - something like:
for cls in feedcls:
with arcpy.da.UpdateCursor(out_data, (fld,)) as cursor:
for row in cursor:
row[0] = span_dict[cls + 'SPAN']
print row[0]
cursor.updateRow(row)
Hi Edward,
It looks like this error may be due to line 28 still referencing the row object from the arcpy.da.SearchCursor(). I was able to reproduce the same behavior. However, if I change the script to the following, the issue goes away.
# Create the search cursor to iterate through table and sum spans and cost with arcpy.da.SearchCursor(fcdtest, ("FeedClass","SHAPE_Length","MGMTCOST",)) as cursor: for row in cursor: if row[0] == "ARS": ARSSPAN += row[1]/55 ARSCOST += row[2] elif row[0] == "ST": STSPAN += row[1]/55 STCOST += row[2] elif row[0] == "S": SSPAN += row[1]/55 SCOST += row[2] elif row[0] == "ARU": ARUSPAN += row[1]/55 ARUCOST += row[2] elif row[0] == "UT": UTSPAN += row[1]/55 UTCOST += row[2] elif row[0] == "U": USPAN += row[1]/55 UCOST += row[2] fld = "YR2015" feedcls = ["ARS","ST","S","ARU","UT","U"] for cls in feedcls: with arcpy.da.UpdateCursor(out_data, (fld,)) as cursor: for row in cursor: row[0] = cls + 'SPAN' cursor.updateRow(row)
Hi Christian,
Thanks for correcting that error in my code. Unfortunately, it hasn't resolved the issue with the UpdateCursor entirely.
To provide further context, the field I'm attempting to write to is a long integer type. The variable list shows
ARSSPAN as an int; however, for row[0] it's listed as a string. How do I make that string become the int variable I want to get the value from? Even though in this case it's 0.
ensure that there are no nulls in the field(s) before calculating on the field. Are the results expected too be float, int or string? This should be coded for or queried out before running
I've checked my sample dataset and there are values for shape_length in each row. Both the span count (eg. ARSSPAN) and cost (eg. ARSCOST) are intended to be int variables.
Edward, I was more worried about working with nulls in the other columns. It is a topic of interest lately for some reason Before I forget ... # 18 ... Those pesky <null> things...
Thank you for your insight. I'm sure that post will alleviate forthcoming issues. I'm really struggling with referencing a variable when the variable name is formed through concatenation. I recall seeing many top quality posts from you when I worked in Avenue. I'm a beginner programmer in Python and can't get over this hurdle.
Converting a string to the variable name in Python use eval().
for cls in feedcls:
with arcpy.da.UpdateCursor(out_data, (fld,)) as cursor:
for row in cursor:
row[0] = eval(cls + 'SPAN')
print row[0]
cursor.updateRow(row)
I see what you're doing here and it works, however I wouldn't recommend this approach as eval will run any python code, its a fairly large 'backdoor' so to speak (enables people to potentially inject malicious python code to run inside your code.. not so dangerous for a desktop script with known users, but could potentially compromise an entire organization if it was web based.)
Essentially eval is extracting the value from that concatenated string variable name by simply evaluating the variable name which returns the associated value, then assigning it to row[0].
Instead, I'd recommend instantiating a dictionary where the keys are your string keywords i.e.: "ARSSPAN" and the values are the associated int value. Then populate this dictionary in your SearchCursor loop, rather than simply assigning the variable names.
Then instead of using eval, you can use a string as the key in your dictionary - something like:
for cls in feedcls:
with arcpy.da.UpdateCursor(out_data, (fld,)) as cursor:
for row in cursor:
row[0] = span_dict[cls + 'SPAN']
print row[0]
cursor.updateRow(row)