Calculate Field with Code Block Python Script?

11374
15
Jump to solution
11-14-2018 01:46 PM
ZacharyHart
Occasional Contributor III

I've spent quite a bit of time looking at all the similar issues on GeoNet and Stack Exchange but I still can't find an answer. I'm sure that someone will be quick to say that I should use a cursor, but this exact same code works in ModelBuilder just fine!

Is there the potential for a carriage return or something? I copied and pasted my codeblock so that might be a possibility.  Here's my code (the FC in question does indeed have a field called 'BEARING'):

# Add Quandrant Bearing Field
arcpy.AddField_management(BoundSplit, "Q_BEARING", "TEXT", "", "", "", "", "NULLABLE", "NON_REQUIRED", "")

# Calculate Quadrant Bearing
expression = """ DD_DMS_Line(!BEARING!,{0}) """.format(correction)
arcpy.AddMessage(expression)
codeblock = """def DD_DMS_Line(bearing, correction=0):
 value = bearing + correction
 if value <= 90:
 numb = value
 prefix = "N"
 suffix = "E"
 elif value > 90 and value < 180:
 numb = 180 - value
 prefix = "S"
 suffix = "E"
 elif value >= 180 and value < 270:
 numb = value - 180
 prefix = "S"
 suffix = "W"
 elif value > 270 and value <= 360:
 numb = 360 - value
 prefix = "N"
 suffix = "W"
 elif value > 360:
 numb = value - 360
 prefix = "N"
 suffix = "E"

 degrees = int(numb)
 submin = abs( (numb - int(numb) ) * 60)
 minutes = int(submin)
 subseconds = abs((submin-int(submin)) * 60)
 notation = prefix + str(degrees) + u"\u00b0" + str(minutes) + "\'" +\
 str(subseconds)[0:5] + "\"" + suffix
 return notation"""

arcpy.CalculateField_management(BoundSplit, "Q_BEARING", expression, "PYTHON", codeblock)

My expression appears to be fine (highlighted in this image).

ugh, been banging my head against the wall on this one!

15 Replies
DanPatterson_Retired
MVP Emeritus

The key was the good nights sleep.  Glad it worked out

AndresCastillo
MVP Regular Contributor
0 Kudos
ModyBuchbinder
Esri Regular Contributor

Hi Zachary

If you already works in Python why not writing an UpdateCursor instead of using the Calculate field.

It is so much easier with complex calculations.

Have Fun

XanderBakker
Esri Esteemed Contributor

I totally agree with modybsystematics-co-il-esridist . You probably should use something like this (I'm including the code snippet Dan provided), which will be much easier to maintain:

def main():
    import arcpy

    # define all your variables
    fc = "path to your table or featureclass BoundSplit"
    fld_bearing = "BEARING"
    fld_q_bearing = "Q_BEARING"

    # Add Quandrant Bearing Field
    arcpy.AddField_management(fc, fld_bearing, "TEXT", "", "", "", "", "NULLABLE", "NON_REQUIRED", "")

    # use an update cursor
    flds = (fld_bearing, fld_q_bearing)
    with arcpy.da.UpdateCursor(fc, flds) as curs:
        for row in curs:
            bearing_val = row[0]
            bearing_txt = DD_DMS_Line(bearing_val, 0)
            row[1] = bearing_txt
            curs.updateRow(row)


def DD_DMS_Line(bearing, correction=0):
    # comment line
     value = bearing + correction
     if value <= 90:
         numb = value
         prefix = "N"
         suffix = "E"
     elif value > 90 and value < 180:
         numb = 180 - value
         prefix = "S"
         suffix = "E"
     elif value >= 180 and value < 270:
         numb = value - 180
         prefix = "S"
         suffix = "W"
     elif value > 270 and value <= 360:
         numb = 360 - value
         prefix = "N"
         suffix = "W"
     elif value > 360:
         numb = value - 360
         prefix = "N"
         suffix = "E"
     degrees = int(numb)
     submin = abs( (numb - int(numb) ) * 60)
     minutes = int(submin)
     subseconds = abs((submin-int(submin)) * 60)
     notation = prefix + str(degrees) + u"\u00b0" + str(minutes) + "\'" +\
     str(subseconds)[0:5] + "\"" + suffix
     return notation

if __name__ == '__main__':
    main()
ZacharyHart
Occasional Contributor III

Xander Bakker‌ I know...you are right. I submit to this as like every thread and experienced python developer says this is a better way to go. In an effort to make my code better and to add some value to this thread I will reconfigure my code to use a cursor to do the field calculation. Many thanks. If anyone thinks it would be of value I'll post the final product here.

XanderBakker
Esri Esteemed Contributor

It is always a good thing to share the final solution back to the community.