1

I'm attempting to create labels for a feature class that labels each feature "[ParentFeatureName] - [ThisFeatureID]". I found a code snippet on Esri support that should fit the bill (with the variable names and return changed as needed):

def FindLabel ([keyField], [FirstLabel]):
    import arcpy

    key1 = [keyField] # Key field in feature class
    key2 = "ID"   # Key field in related table
    L = [FirstLabel] # Label field in feature class
    L2 = "Label2"   # Label field in related table
    myDataTable = r"ExampleTable"   # Path to related table

    cur = arcpy.da.SearchCursor(myDataTable, [key2, L2])
    for row in cur:
        if str(key1) == str(row[0]): 
            L = L + " " + str(row[1])
    return L

But no labels appeared! So I did some experimenting:

  1. I did a sanity-check in the Python pane to make sure that the comparison is valid (it is)
  2. I started commenting out code to see where it bombed.

I had expected that commenting out the for loop and the assignment of L would label my features with L, but to my surprise, there were still no labels. Only when I also commented out cur = arcpy.da.SearchCursor(myDataTable, [key2, L2]) did the labels appear!

The same behavior also happens using the legacy arcpy.SearchCursor.

Why is that line of code preventing the labels from appearing and how do I work around it?

1

Provided the composition of myDatatable is correct(ie. fully qualified or obtained through some means that guarantees the validity), I would recommend managing the life of the insert cursor by explicitly releasing the cursor before the return as in:

import arcpy
def FindLabel ([OBJECTID], [gns_NAME]):

    key1 = [OBJECTID] # Key field in feature class
    key2 = "PARENT_OBJECTID"   # Key field in related table
    L = [gns_NAME] # Label field in feature class
    L2 = "TOYS"   # Label field in related table
    myDataTable = r"C:\\se_LabelFromRelated\\Goodies.gdb\\Child_StandAlone_Table"

    cur = arcpy.da.SearchCursor(myDataTable, [key2, L2])
    for row in cur:
        if str(key1) == str(row[0]): 
            L = L + "\n" + str(row[1])
    del cur
    return L

This works for me. (When using this method, any changes to the child_table will require a screen refresh [pan,zoom, refresh] to see the label changes) enter image description here

While this solution may prove viable for small datasets, it's going to struggle with large datasets due to the unconstrained nature of the search cursor and iteration of the entire related table for each parent feature. If you consider the syntax for SearchCursor:

SearchCursor (in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause})

This solution would benefit from the addition of a {where_clause} to limit the child records considered in the label rendering.

where_clause = [key2] + " = " + str([OBJECTID])
cur = arcpy.da.SearchCursor(myDataTable, [key2, L2], where_clause)

A performance oriented re-factor would look like

import arcpy
key2 = "PARENT_OBJECTID"   # Key field in related table
L2 = "TOYS"   # Label field in related table
table_view_path = arcpy.mapping.ListTableViews(arcpy.mapping.MapDocument('CURRENT'))[0].workspacePath + '\\'
related_table_name = r"Child_StandAlone_Table"
myDataTable = table_view_path + related_table_name # Path to related table

def FindLabel ([OBJECTID], [gns_NAME]):
    L = [gns_NAME] # Label field in feature class

    cur = arcpy.da.SearchCursor(myDataTable, [L2], key2 + r"=" + str([OBJECTID]))
    for row in cur:
        L = L + "\n" + str(row[0])
    del cur
    return L
  • Your answer didn't work for me initially, but it led me down the right path. The string I was using for myDataTable was only "Tablename" (which did not give a runtime error when I verified the script in ArcGIS Pro) instead of "DB.gdb/Tablename". Once I added the database to the path, it worked fine, even without del cur. – Soulis Oct 2 at 14:52
  • Glad it got you pointed in the right direction. If you choose not to add the del cursor statement, I can guarantee ArcMap will experience memory loss over a prolonged session and may lead to crashing @ some point. AS with most things ArcGIS, your mileage may vary :) – Robbie Symborski Oct 2 at 15:55
  • 1
    *as a side note ... no one could speculate on your composition of my_datatable because you omitted it in your question ... may be useful to edit the question to include a representation of what you had that failed for comparison sake to what we know does work. – Robbie Symborski Oct 2 at 15:57
  • Fair point, I've edited in an example table name into the code. If you want to edit in pointing out my path mistake, I think that'd make things more clear than having to read the comments. – Soulis Oct 2 at 16:05
  • Also, thanks for pointing out the memory loss without the del cursor statement. I'm from a c# background, so I didn't know what the lifetimes of variables are like in python. – Soulis Oct 2 at 16:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.