Script works in notebooks but not in a toolbox

176
5
Jump to solution
2 weeks ago
BrandonMcAlister
Occasional Contributor

Why does my code work in arcgis notebooks but when I run it from a tool box it does not preform every function?

Specifically, the below code block calculates X and Y, then checks for duplicate records and throws and error if it finds any. Then it will inserts the calculated rows into the master file. Then creates a definition query so only the added shapes are shown. Then it updates the shape with the X and Y calculated earlier of the inserted rows based on a unique identifier.  It works as intended when run in notebooks. However, when I export to a .py and put it in a tool box as a script it only adds the last row and instead of updating the shape of added records it updates the shape of all records in the file which are set to null as they are calculated at the end of the script(not shown).

Why...

 

P.S. I have tunnel vision and cannot see the issue

 

edit: change lines 4 - 9 to remove a while statement

 

#Updates attribute table and inserts PI with multiple parcels into master file

#Gets array of layer names
lyrlist = MP.listLayers()
lyrname = []
for l in lyrlist:
    lyrname.append(l.name)

if "Multiple_Parcel_PIs" in lyrname:
    MultiParcel = MP.listLayers("Multiple_Parcel_PIs")[0] #create object for Multiple PI Layer
    MultiParcel.updateDefinitionQueries(None) #clears definition queries
    MTotal = int(str(arcpy.management.GetCount(MultiParcel))) #Get total count of features
    PreGTotal = int(str(arcpy.management.GetCount(Geocode)))
        
    #Calculate Feature Geometry State Plane
    arcpy.management.CalculateGeometryAttributes(
    in_features = MultiParcel,
    geometry_property = "X_Coordinate POINT_X;Y_Coordinate POINT_Y",
    length_unit = "",
    area_unit = "",
    coordinate_system = 'PROJCS["NAD_1983_2011_StatePlane_New_Jersey_FIPS_2900_Ft_US",GEOGCS["GCS_NAD_1983_2011",DATUM["D_NAD_1983_2011",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",492125.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-74.5],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",38.83333333333334],UNIT["Foot_US",0.3048006096012192]],VERTCS["NAVD88_height_(ftUS)",VDATUM["North_American_Vertical_Datum_1988"],PARAMETER["Vertical_Shift",0.0],PARAMETER["Direction",1.0],UNIT["Foot_US",0.3048006096012192]]',
    coordinate_format = "SAME_AS_INPUT"
    )
        
    arcpy.SetProgressorLabel("Combining Shapefiles") #Changes tool progress label
    arcpy.SetProgressorPosition(1) 
        
    #Hides features that were unable to be verified
    MultiParcel.definitionQuery = "Locational_Comments IS NOT NULL"
        
    #Updates locations quality to reviewed and verified in GIS
    upcursor = arcpy.da.UpdateCursor(MultiParcel, "location_quality_type_code")
    for row in upcursor:
        row = [60]
        upcursor.updateRow(row)
        
    MultiParcel.updateDefinitionQueries(None)#Clears all definition queries
        
    MultiParcelList = [] #creates empty list for tracking PIs that repeat
    PILIST = [] #creates empty list for tracking PIs
        
    now = datetime.datetime.now() #gets time loop started
        
    Mcursor = arcpy.da.SearchCursor(MultiParcel, ["USER_pi_id"]) #gets attribute information
    Marray = Mcursor._as_narray() #turns cursor into array
        
    i = 0 
    while i < len(Marray):
        PI = Marray[t][0] #gets PI from array
        if PI not in PILIST:
            PILIST.append(PI) #appends PI to list
        arcpy.management.SelectLayerByAttribute(MultiParcel, where_clause = "USER_pi_id = " + "'" + str(PI) + "'") #Selects features by unique pi id in
        count = arcpy.management.GetCount(MultiParcel) #Gets count of selected features
        if int(str(count)) > 1 and PI not in MultiParcelList: #checks if multiple records are selected
            MultiParcelList.append(PI) #adds PI to list if multiple records are selected
            arcpy.AddWarning("PI ID: " + str(PI) + ", has multiple parcels.") #adds warning
        i += 1 #adds 1 to iterable varaible
            
    arcpy.SetProgressorPosition(25)#Sets progress bar positionto 25/100
        
    if MultiParcelList:
        MultiParcelTuple = tuple(MultiParcelList) #turns list into tuple
        MultiParcel.definitionQuery = "USER_pi_id NOT IN " + str(MultiParcelTuple)
        arcpy.ExecuteError("Multiple PIs were detected, please correct issue in Multiple_Parcel_PI layer and run again.")
        
    MP.clearSelection() #clears selection in map
    cursor = arcpy.da.SearchCursor(MultiParcel, fields) #gets all attributes
    array = cursor._as_narray() #turns it into an array
        
    #Add PIs from Multi Parcel PI layer to new dataset
    incursor = arcpy.da.InsertCursor(Geocode, fields, None, False) #creates insert cursor
    edit.startEditing(False, False) #starts edit session
    for row in array: #loops through array
        arcpy.AddMessage(str(row))
        incursor.insertRow(row) #adds row to Geocode layer
    edit.stopEditing(True) #stops edit session
    del incursor #deletes insert cursor
        
    PITuple = tuple(PILIST) #turns array into tuple
    arcpy.AddMessage(str(PITuple))
    Geocode.definitionQuery = "USER_pi_id in" + str(PITuple) #Creates new definition query
        
    break
        
    Gcursor = arcpy.da.SearchCursor(Geocode, ["USER_pi_id", "X_Coordinate", "Y_Coordinate"]) #Creates search cursor for added PIs
    Garray = Gcursor._as_narray() #turns it into array
    print(len(Garray))
    arcpy.SetProgressorPosition(50) #updates progress bar
        
    #Loop through added PIs and updates their shape position all import with 0 X and 0 Y
    i = 0 
    while i < len(Garray):
        pi = Garray[p][0] #gets PI from Garray
        east = Garray[p][1] #gets X from Garray
        north = Garray[p][2] #gets Y from Garray
        point = arcpy.Point(east, north) #makes an arcpy point
        arcpy.management.SelectLayerByAttribute(Geocode, where_clause = "USER_pi_id = " + "'" + str(pi) + "'") #selects by PI
        upcursor = arcpy.da.UpdateCursor(Geocode, ["SHAPE@"]) #Creates update cursor for selected record
        edit.startEditing(False, False) #starts edit session
        for row in upcursor: #updates selected records shape
            row = [point]
            upcursor.updateRow(row)
        i += 1
        edit.stopEditing(True) #stops edit session
    #Deletes created cursors
    del Gcursor
    del Garray
    del Mcursor
    del Marray
    del cursor
    del array
        
    Geocode.updateDefinitionQueries(None) #Clears definition queries
        
    arcpy.SetProgressorPosition(99) #updates progress bar
        
    end = datetime.datetime.now() #gets time loop ended
    elapsed = end - now #does math for run time
    arcpy.AddMessage("Combining shapefiles elapse time: " + str(elapsed)) #adds arcpy message
    NewTotal = PreGTotal + MTotal
    GTotal = int(str(arcpy.management.GetCount(Geocode)))
    if NewTotal != GTotal:
            arcpy.ExecuteError("Contact CSRR GIS Team, combining MultiParcel to Geocode failed.")

 

 

Thanks,
Brandon
0 Kudos
1 Solution

Accepted Solutions
DanPatterson
MVP Esteemed Contributor

when using select by attributes within any kind of loop it is a wise idea to clear the selection after you exit the loop to make sure selections don't persist.  Use the same tool to ensure it happens using the 'selection type' parameter

Select Layer By Attribute (Data Management)—ArcGIS Pro | Documentation


... sort of retired...

View solution in original post

0 Kudos
5 Replies
BrandonMcAlister
Occasional Contributor

I have narrowed it down to the cursor I create on line 68 only has one feature in it, But when I run it in my notebook it has all 15???

Thanks,
Brandon
0 Kudos
BrandonMcAlister
Occasional Contributor

I have further narrowed down the issue to the while statement on line 48. When I remove that loop the cursor has all 15 records. When the loop is there only 1 record shows up in the cursor. 

Within the loop there is a select by attribute function, but I have the clearSelection() method right after the code.

Is the code simply running too fast that it does not recognize that no features are selected?

Thanks,
Brandon
0 Kudos
DanPatterson
MVP Esteemed Contributor

when using select by attributes within any kind of loop it is a wise idea to clear the selection after you exit the loop to make sure selections don't persist.  Use the same tool to ensure it happens using the 'selection type' parameter

Select Layer By Attribute (Data Management)—ArcGIS Pro | Documentation


... sort of retired...
0 Kudos
BrandonMcAlister
Occasional Contributor

@DanPatterson  so I just added arcpy.management.SelectLayerByAttributes(MultiParcel, where_clause = none) and I am getting all 15 records now. 

In all other portions of my code I have used arcpy.mp.ArcGISProject("Current").activemap.clearSelection() in loops and it has always cleared any selection made by arcpy.management.SelectLayerByAttributes(). 

When comparing two different loops I do no see any difference in structure. Do you have any insight as to why it would fail in this one instance?

(This other scripts are also run from the tool box)

Thanks,
Brandon
0 Kudos
DanPatterson
MVP Esteemed Contributor

I trust arcpy management and don't work with the arcgis module enough to ensure that activatemap.clearSelection() performs that exact clearing of selections.  You could examine its code if you want to delve further


... sort of retired...
0 Kudos