As @Andy said, you're using calculate field in a double cursor loop, it's the cursor that's locking the calculate field.. instead try it like this:
#create search cursor to access table. may need to change field name with other data.
with arcpy.da.SearchCursor(buffer, ["buff_id"]) as buffCursor:
for row in buffCursor:
#select one buffer
query = """ "buff_id" = %s """ %row[0]
arcpy.SelectLayerByAttribute_management(buffer, "NEW_SELECTION", query)
#define clip out path
clip_out = "LS" + str(row[0])
#clip w one buffer
arcpy.Clip_analysis(landcov, buffer, clip_out)
#add fields to clip_out
arcpy.AddField_management(clip_out, "clip_id", "TEXT", 20)
arcpy.AddField_management(clip_out, "area_ha", "FLOAT")
#create updatecursor for new clip_out
with arcpy.da.UpdateCursor(clip_out, ["clip_id", "area_ha","SHAPE@AREA"]) as clipCursor:
for polys in clipCursor:
#calc geom for area ha
polys[1] = polys[2].area / 10000 # A hectare is 10000 square metres
#field calc for buffer id
polys[0] = row[0]
clipCursor.updateRow(polys) # IMPORTANT don't forget to commit the update
I've changed your cursors to with blocks, this handles the removing when the cursor passes out of scope. I am assuming here that your data is in a spatial reference with units in metres, see this post about other units (like feet) for a simple conversion but if your data is in geographical units you can choose a suitable projected coordinate system (for example WGS84 UTM Zone 55 south, EPSG code 32755) and project the geometry on the fly:
CalcSR = arcpy.SpatialReference(32755) # declare this outside the loop using EPSG code
with arcpy.da.UpdateCursor(clip_out, ["clip_id", "area_ha","SHAPE@"]) as clipCursor:
for polys in clipCursor:
#calc geom for area ha, project to UTM and calculate from the area
polys[1] = polys[2].projectAs(CalcSR).area / 10000 # A hectare is 10000 square metres
#field calc for buffer id
polys[0] = row[0]
clipCursor.updateRow(polys) # IMPORTANT don't forget to commit the update
Either way though the use of a cursor-in-cursor loop is discouraged, it's better to build a list and then iterate:
#create list to access table. may need to change field name with other data.
# builds a list of all buff_id values... you might want to do something about
# removing duplicates but this works as an example
AllBuffID = [r[0] for r in arcpy.da.SearchCursor(buffer, ["buff_id"])]
for thisBuffID in AllBuffID:
#select one buffer
query = """ "buff_id" = %s """ %thisBuffID
arcpy.SelectLayerByAttribute_management(buffer, "NEW_SELECTION", query)
#define clip out path
clip_out = "LS" + str(thisBuffID)
#clip w one buffer
arcpy.Clip_analysis(landcov, buffer, clip_out)
#add fields to clip_out
arcpy.AddField_management(clip_out, "clip_id", "TEXT", 20)
arcpy.AddField_management(clip_out, "area_ha", "FLOAT")
#create updatecursor for new clip_out
with arcpy.da.UpdateCursor(clip_out, ["clip_id", "area_ha","SHAPE@"]) as clipCursor:
for polys in clipCursor:
#calc geom for area ha, project to UTM and calculate from the area
polys[1] = polys[2] / 10000 # A hectare is 10000 square metres
#field calc for buffer id
polys[0] = thisBuffID
clipCursor.updateRow(polys) # IMPORTANT don't forget to commit the update