1

I am working on a script that iterates through the records of "feature class A", performs a spatial selection (flow tracing) with each individual "A" record on "feature class B" and then field calculates an attribute from "A" into the resulting selected records in "B"

Basically for each downstream-most node on a sewer pipe network, trace upstream and assign the ID of that downstream node to all upstream features.

The attribute value will always be a whole number, but sometimes field in A is formatted as text and sometimes as a number.

I can successfully perform this calulation if:

A is formatted as TEXT

and

B is formatted as LONG

the operation fails to calculate anything if:

A is formatted as LONG

and

B is Formatted as LONG

What am I missing so that this will work for both potential input cases if the ID for A is either text whole number or an integer whole number format?

...
for row in cursor:
    ID = (str(row.getValue(str(flagname))))
    whereclause = ((str(flagname)) +str(' = ') + "'%s'" %ID)
    fc=str(r"outfalls_lyr")
    arcpy.MakeFeatureLayer_management(traceflag, fc)

    try:
        arcpy.SelectLayerByAttribute_management(fc, "NEW_SELECTION",str(whereclause))
        arcpy.MakeFeatureLayer_management( fc,r"in_memory\temp_of")
        arcpy.TraceGeometricNetwork_management(geomnet, r"in_memory\outNet",r"in_memory\temp_of" , "TRACE_UPSTREAM", "", "", "","", "", "NO_TRACE_ENDS", "NO_TRACE_INDETERMINATE_FLOW", "", "", "AS_IS", "", "", "", "AS_IS")
        for layer in arcpy.mapping.Layer(r"in_memory\outNet"):
            try:
                print arcpy.mapping.ListLayers(layer)
                calc = str('"%s"' %ID)
                arcpy.CalculateField_management (layer, fieldname, calc,"","")
            except:
                print arcpy.GetMessages()

    except:
        print arcpy.GetMessages()

Cross-posted to Stack Overflow, too.

2
  • What happens when it does not work. Do you get an error message? If so, please edit your post to include the entire error stack. Oct 30, 2019 at 21:50
  • There's no error, just nothing calculated into the target field.
    – Zipper1365
    Oct 31, 2019 at 11:29

2 Answers 2

2

You should specify your expression type (eg, "PYTHON"), but this will depend on which version of ArcGIS/arcpy you are using. "PYTHON" for ArcMap is required, if you don't want it to default to "VB" (visual basic!). You can use VB if you wish, but it would be unusual to embed this into a Python (arcpy) script. (I think ArcGIS Pro defaults to "PYTHON3").

But I think the main problem is that you have set your calc string to include double quotation marks (") at the beginning and end within the string value itself when you do: calc = str('"%s"' %ID). This will result in a string value like "123" INCLUDING the double quotes which cannot be converted to a number.

Try this instead:

arcpy.CalculateField_management(layer, fieldname, ID, "PYTHON", "")

ID is already a string (has already been converted and cast to string earlier in the script), so no need to do it again, and it doesn't include the problematic extra quotation marks in the string value.

Now you can also delete the line: calc = str('"%s"' %ID)

As an aside, don't use str() to cast strings to strings. It is redundant and also makes your code hard to read. For example, str(' = ') is pointless. Just use ' = '. Only use str() if you need to convert something that is NOT a string into a string.

1
  • it appears to yield the same result. perhaps the issue iw with my selection query (whereclause) to make the flow tracing flag layer "in_memory\temp_of"
    – Zipper1365
    Oct 31, 2019 at 12:13
0

The problem appears to have been in how the selection query was parsed and executed. For one of the field types, it returned a an empty selection, so there were no trace flags generated from which to perform the upstream trace selection. this returned an empty trace result so there were no record into which to calculate the ID.

adding a test for the source field type appears to have solved the problem.

I am positive that there are more efficient and cleaner way to write this, but the updated code below DOES appear to perform the desired results in both cases ( source field is TEXT or source field is LONG) so it's an adequate fix for my purposes.

cursor = arcpy.SearchCursor(traceflag)

fields = arcpy.ListFields(traceflag)
for field in fields:
    if field.name == flagname and field.type == 'String':
        typeIsString = "True"
    elif field.name == flagname and not field.type == 'String':
        typeIsString = "False"


for row in cursor:
    if typeIsString == "True":
        ID = str((row.getValue(str(flagname))))
    elif typeIsString == "False":
        ID = int((row.getValue(str((flagname)))))
whereclause = (flagname + ' = ' + `ID`)
fc=str(r"outfalls_lyr")
arcpy.MakeFeatureLayer_management(traceflag, fc)

try:
    arcpy.SelectLayerByAttribute_management(fc, "NEW_SELECTION",str(whereclause))
    arcpy.MakeFeatureLayer_management( fc,r"in_memory\temp_of")
    arcpy.TraceGeometricNetwork_management(geomnet, r"in_memory\outNet",r"in_memory\temp_of" , "TRACE_UPSTREAM", "", "", "","", "", "NO_TRACE_ENDS", "NO_TRACE_INDETERMINATE_FLOW", "", "", "AS_IS", "", "", "", "AS_IS")
    for layer in arcpy.mapping.Layer(r"in_memory\outNet"):
        try:
            print arcpy.mapping.ListLayers(layer)
            calc = str('"%s"' %ID)
            arcpy.CalculateField_management(layer, fieldname, ID, "PYTHON", "")
        except:
            print arcpy.GetMessages()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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