Monday, 4 December 2017

arcgis 10.1 - Handling ArcPy locks in Python script?



  • i am writing script which uses different Tools of arcgis and implementing different functionalities ..

  • My script consists in different Functions running in an order. Each function is connected to each other , and works on layers and performs functions like(update cursor, search cursor )

  • When function1 finishes execution funciton2 starts and works on the same layer on which first one was working.



The problem is here function2 generates wrong results or works wrong.


works wrong means if a loop is defined to 5 iterations it will runs more then 5 times. like 20, 30 times and generates different results of one value.


When i run each function separately it will works fine. but when i run function in one script it will create problems.


My findings of this are LOCKS which are creating the problem.


Sample Structure of my script:


import arcpy  
import math
import sys
import traceback

from arcpy import env

class test:
def __init__(self, workSpace):
self.workSpace = workSpace

# Add Fields
def function1(self):
# Script
return;

# Generate Report
def function2(self):
# Script
rows = arcpy.SearchCursor(self.mapLayerFinal,"","","Shape_Area")
row = rows.next()
while row:
area = row.Shape_Area
print "function2"
destination_cursor = arcpy.UpdateCursor(self.censusLayer, '"DISTRICT_ID" = '+ str(district_id))
row1 = destination_cursor.next()

while row1:
row1.setValue("District_Area",area)
destination_cursor.updateRow(row1)

row1 = destination_cursor.next()

row = rows.next()
return;

t = test(workSpace)

t.function1()
t2 = test(workSpace)
t2.function2()

NOTE: code is tested and working correct if each function is executed separately



Answer



There's a few little problems here.. expanding on my comment you must release your cursor before using it again I have edited your code with the appropriate del statements and comments:


import arcpy, math, sys, traceback  # Condense onto one line
from arcpy import env # you're not using this, why import it?


class test:
def __init__(self, workSpace):
self.workSpace = workSpace

# Add Fields
def function1(self):
# Script
return;

# Generate Report

def function2(self):
# Script
rows = arcpy.SearchCursor(self.mapLayerFinal,"","","Shape_Area")
row = rows.next()
while row:
area = row.Shape_Area
print "function2"
# where does district_id come from????, let's assume it's in the table
district_id = row.DISTRICT_ID
destination_cursor = arcpy.UpdateCursor(self.censusLayer, '"DISTRICT_ID" = '+ str(district_id))

row1 = destination_cursor.next()
while row1:
row1.setValue("District_Area",area)
destination_cursor.updateRow(row1)
row1 = destination_cursor.next()

#release the lock by removing the cursor
del row1
del destination_cursor


row = rows.next()
return;

t = test(workSpace)
t.function1()
t2 = test(workSpace)
t2.function2()

Consider using the arcpy.da cursors, it makes the code so much more compact and is compatable with with statements handling disposal, this is the same function with arcpy.da cursors:


def function2(self):  

# Script, using arcpy.da
with arcpy.da.SearchCursor(self.mapLayerFinal,["Shape_Area","DISTRICT_ID"]) as rows:
for row in rows:
area = row[0]
district_id = row[1] # I assume this is where it comes from
arcpy.AddMessage("Function 2") # same as print on command line, but works in tool window too
with arcpy.da.UpdateCursor(self.censusLayer,"District_Area",'"DISTRICT_ID" = '+ str(district_id)) as destination_cursor:
for row1 in destination_cursor:
row1[0] = area
destination_cursor.updateRow(row1)

return;

When using an arcpy.da cursor you declare the field names (in order) that you want the object to have and then index them, irrespective of the order in the table; if a feature class has fields a, b, c and d and you declare a cursor with fields d,b then the row object indexes d at 0 and b at 1... this alleviates the need for getValue and setValue by direct indexing. You will only get problems if the fields are not found! The best thing is iteration: for row in cursor: is so much better (more pythonic) than while...next() IMO.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...