Select to view content in your preferred language

GIS Tutorial for Python Scripting 2-7 cursor problem

1550
3
10-18-2016 05:31 AM
Ericvan_Rees
Emerging Contributor

This is the example code of tutorial 2-7 of GIS Tutorial for Python Scripting by David Allen. I followed the example code from the book, but the cursor in line 83 wasn't there so I added it myself and it's not working properly. I´m not even sure I used the right cursor. Any help would be very much appreciated on getting it to work.

I'm using ArcMap 10.2.2 and I noticed env.overwriteOutput = True isn´t working properly, which could also be a problem here.

try:
    # import the modules
    import arcpy
    from arcpy import env

    # set up the environment
    env.workspace = "C:/EsriPress/GISTPython/MyExercises"
    env.overwriteOutput = True

    # prompt the user for the input table
    inTable = arcpy.GetParameterAsText(0)
    # when this is set up as a cursor tool, set the input to tables only

    # Get the fields from the input
    fields = arcpy.ListFields(inTable)

    # Create a fieldinfo object
    fieldinfo = arcpy.FieldInfo()

    # Define a fieldinfo object to bring only certain fields into the view
    # inci_no, alm_date, arv_date, inci_type
    # descript, station, shift, city
    # number, st_prefix, street, st_type, st_suffix
    # (you can´t add new fields to a table view, so reuse a discarded one)
    # Change the name of addr_2 to GeoAddress in the output table
    # Code was copied and modified from Help screen

    # interate through the fields and set them to fieldinfo
    for field in fields:
        if field.name == "inci_no":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "alm_date":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "alm_time":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "arv_date":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "arv.time":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "inci_type":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "descript":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "station":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "shift":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "city":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "number":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "st_prefix":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "street":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "st_type":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "st_suffix":
            fieldinfo.addField(field.name, field.name , "VISIBLE", "")
        elif field.name == "addr_2":
            fieldinfo.addField(field.name, "GeoAddress" , "VISIBLE", "")
        else:
            fieldinfo.addField(field.name, field.name , "HIDDEN", "")

    # Create a table view of the input table
    # The created fire_view table will have fields as set in fieldinfo object
    arcpy.MakeTableView_management(inTable, "fire_view", "", "", fieldinfo)

    # Do the address formatting into GeoAddress for the whole table
    # Concatenate number + st_prefix + street + st_type + st_suffix and remove spaces
    arcpy.CalculateField_management("fire_view","GeoAddress","str(!number!) + ' ' + !st_prefix!.strip() + ' ' + !street!.strip() + ' ' + !st_type!.strip() + ' ' + !st_suffix!.srip()", "PYTHON")

    # Create new geodatabase to store results for year
    # ("Fire Files for " + last 4 digits of file name)
    gdbName = "Fire_Files_For_" + inTable[-8:]
    arcpy.CreateFileGDB_management("C:\\EsriPress\\GISTPython\\MyExercises",gdbName)

    # Use cursor to find each unique city name and add it to a list.append
    # City names included may differ from file to file.
    # Set up a list to hold unique ity names.    

    # Start cursor iteration
    with arcpy.da.SearchCursor(inTable, ["city"]) as fireCursor:        
        for row in fireCursor:
            cityList = []
            cityName = row[23]
            if cityName not in cityList:
                cityList.append(cityName)
    # Result is a list object with all the unique values of the CITY field
        del row
        arcpy.AddWarning("Made the list of city names")

    # Use the names in the list object to select records
    for name in cityList:
        cityQuery = '"city" = \'' + name + '\''

        arcpy.SelectLayerByAttribute_management("fire_view", "NEW_SELECTION",cityQuery)

        newTable = "C:\\EsriPress\\GISTPython\\MyExercises\\" + gdbName + ".gdb\\" + name.replace(" ","_")

        itemCount = int(arcpy.GetCount_management("fire_view").getOutput(0))

        arcpy.AddWarning("A tale called " + newTable + " was created with " + str(itemCount) + " rows.")

except arcpy.ExecuteError:
    print arcpy.GetMessages(2)
except:
    print "Process did not complete."
        
0 Kudos
3 Replies
BrittneyWhite1
Esri Contributor

Your cursor in line 83 is only set up to return the "city" field. From the help, The da.SearchCursor: "Returns an iterator of tuples. The order of values in the tuple matches the order of fields specified by the field_names argument" (emphasis added). Since you have only specified the "city" field, each row is a tuple that has one item in it, which is the value in the "city" field. You can check this by printing out the value of each row.

That means your line 86:

cityName = row[23]

returns nothing because there is no index position 23 in your row.

Ericvan_Rees
Emerging Contributor

Thanks for your help. Would the problem be solved if I use

cityName = row[0]

instead of:

cityName = row[43] ?

0 Kudos
BlakeTerhune
MVP Regular Contributor

Yes. Like Brittney mentioned, you create fireCursor with only one field (city) so it will only have one index position, which is 0. The other problem is that your recreating cityList in your loop for each row so it will only ever have the last row value in it. You'd have to create your list variable before you get into the loop.

cityList = []
with arcpy.da.SearchCursor(inTable, ["city"]) as fireCursor:
    for row in fireCursor:
        cityName = row[0]
        if cityName not in cityList:
            cityList.append(cityName)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Alternatively, you can simplify the whole thing by using set comprehension.

cityList = {row[0] for row in arcpy.da.SearchCursor(inTable, ["city"])}‍‍‍‍

Which gives you a set object that only has the unique values in the city field of inTable.

If this was in a RDBMS like SQL Server or Oracle, you could use a sql_clause parameter when you create the search cursor and use DISTINCT.