Select to view content in your preferred language

Moving values within FC works, but not for a List of FCs

5831
27
Jump to solution
01-21-2015 11:37 AM
GabrielBacca-Cortes
Deactivated User

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)

0 Kudos
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

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

View solution in original post

27 Replies
JoshuaBixby
MVP Esteemed Contributor

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.

0 Kudos
GabrielBacca-Cortes
Deactivated User

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

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

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?

0 Kudos
SuryaKant
Deactivated User

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

0 Kudos
XanderBakker
Esri Esteemed Contributor

Yeah, some explanation on the general idea would be helpful. From what I see in your code it doesn’t make much sense:

  • Your create a list of polyline featureclasses in you workspace
  • You loop through the featureclasses
    • for each feature in the current featureclass you append the values of the input fields to a list
    • next you create an update cursor on the same featureclass and start to set the values of the output fields. When doing this you assign the first 4 values of the list (not the additional values appended to the list).

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...

0 Kudos
GabrielBacca-Cortes
Deactivated User

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

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

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?

0 Kudos
GabrielBacca-Cortes
Deactivated User

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

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

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.

0 Kudos