I really don't know how to phrase the question actually. I started by using a calculate field management, except that my codeblock started to run on for hundreds of lines and was hard to read and write in (in notepad++ you see solid orange code), but it worked. Specifically, I could create layers using MakeFeatureLayer that where isolated to the codeblock and never appeared in the table of contents of ArcGIS.
Because I will be handing my code down to others to interpret and modify as suits them I decided to try replacing the calculate field with an update cursor. Currently it is not able to run the MakeFeatureLayer within my For loop that I am using to implement my update cursor and it raises this error code:
MakeFeatureLayer raise e ExecuteError: ERROR 999999: Error executing function. Cannot acquire a lock. Cannot acquire a lock. Failed to execute (MakeFeatureLayer).
Even if I do get it to work though, I do not know if it will try to create a layer outside of the loop over each iteration. (perhaps I could try deleting the layer in each loop after I am finished using it).
Here is a code snipet. Any ideas how to get MakeFeatureLayer working?
# Set local variables
inTable = "Murray Sp2"
def Strike(shape, fid):
....
if length >= 183 and length <= 185:
....
# I next make the shapelyr feature layer out of my current intable(Murray Sp2), but only select the current object being
#calculated by using the where statement to select only the objct with the current FID
arcpy.MakeFeatureLayer_management(inTable, 'shapelyr', '"FID" ='+str(fid))
# I then make the PairedCheck6 feature layer out of my current intable(Zarza data), but excluding the current object being
#calculated by using the where statement to select only objects that do not match the current FID. This layer will be used
#to select the matching dip symble that belongs with the strike symbol for which the azimuth is being calculated
arcpy.MakeFeatureLayer_management(inTable, 'PairedCheck6', '"FID" <>'+str(fid))
....
cursor = arcpy.da.UpdateCursor(inTable, ['Shape@', 'FID', fieldName])
for row in cursor:
row[2] = Strike( row[0], row[1])
cursor.updateRow(row)
Solved! Go to Solution.
Ok, so I figured something out in the end. What I had mentioned just one post above did not work since the feature layer was still connected to the source data which had been locked by the UpdateCursor. Thus what I did was to use the CopyFeatures to create two new shape files and then edit them within my function using SelectLayerByAttribute. However, I found this code be be rather slow and inefficient, so I will be looking into a new way of doing this.
# Import system modules
import arcpy
import os
# Set local variables
datasource = r"C:\Alexsomewhere"
inTable = os.path.join(datasource, "Murray Sp2.shp")
fieldName = "DipDir"
arcpy.CopyFeatures_management(inTable, "C:\Alexsomewhere\shapelyr")
arcpy.CopyFeatures_management(inTable, "C:\Alexsomewhere\PairedCheck6")
def Strike(shape, fid):
# here I have cut out trigonometry that calculates a line direction. 55 is arbitrary and meaningless.
degreeBearing = 55
arcpy.SelectLayerByAttribute_management('shapelyr', 'NEW_SELECTION', "{0} = {1}".format("FID", fid))
arcpy.SelectLayerByAttribute_management('PairedCheck6', 'NEW_SELECTION', "{0} <> {1}".format("FID", fid))
#Next I Select the features from PairedCheck6 that are within a specified distance of the feature for which the azimuth is being calcualted
arcpy.SelectLayerByLocation_management('PairedCheck6', 'WITHIN_A_DISTANCE', 'shapelyr', '11 Meters', 'SUBSET_SELECTION')
# Next I create my curser object which I use to find the TrueCentroid and Length of each of the features Selected in PairedCheck6. Notice that only the selected objects in PairedCheck6 are used.
cursor = arcpy.da.SearchCursor('PairedCheck6',['SHAPE@TRUECENTROID', 'SHAPE@LENGTH'])
#Here I cut out logic to check that I have the correct number of selected rows from PairedCheck6, and if not, try to select the correct ones using their centroids and lengths.
#Once I have the correct number of other object(s) I create a pointgeometry and check its location relative to the current object then modify the degreeBearing that will be passed one last time depending on the result.
#returns the degreebearing value as the dip direction
return degreeBearing
with arcpy.da.UpdateCursor(inTable, ['SHAPE@', 'FID', fieldName]) as cursor:
for row in cursor:
row[2] = Strike( row[0], row[1])
cursor.updateRow(row)
del cursor
del row
You're getting that error because the datasource you're trying to get to it being used by another application (probably ArcMap or ArcCatalog).
I edited the code snippet to include:
Lastly, this code doesn't show the in-memory layers being used anywhere. What is the purpose of making the layers exactly?
I hope this helps. I can't be too sure this will work without seeing the entire code.
datasource = r'path/to/datasource/folder/or/geodatabase'
inTable = os.path.join(datasource,"Murray Sp2")
fidField = arcpy.AddFieldDelimiters(datasource, 'FID')
def Strike(shape, fid):
if length >= 183 and length <= 185:
arcpy.MakeFeatureLayer_management(inTable, 'shapelyr', "{0} = {1}".format(fidField, str(fid)))
arcpy.MakeFeatureLayer_management(inTable, 'PairedCheck6', "{0} <> {1}".format(fidField, str(fid)))
cursor = arcpy.da.UpdateCursor(inTable, ['SHAPE@','FID',fieldName])
for row in cursor:
row[2] = Strike(row[0], row[1])
cursor.updateRow(row)
del cursor
I guess that I should specify that I am working within ArcMap with this code.
I have included more of my code below showing more of what I had at the beginning setting up, and what I use the two layers for. I do not show a huge portion in the middle where I narrow down the the few selected records, and determine if the selected records are located right or left of the record being updated. Thus I end with a IsCentroidRight boolean. Then I return a short integer based on the results of the value of IsCentroidRight.
When I run with those suggestions implemented as below, I now am getting:
Runtime error
Traceback (most recent call last):
File "<string>", line 55, in <module>
RuntimeError: cannot open 'D:/Work/Everything/trial/Murray Sp2'
# Import system modules
import arcpy
import os
# Set environment settings
arcpy.env.workspace = "D:/Work/Everything/trial"
# Set local variables
datasource = "D:/Work/Everything/trial/"
inTable = os.path.join(datasource,"Murray Sp2")
fieldName = "DipDir"
fidField = arcpy.AddFieldDelimiters(datasource, 'FID')
def Strike(shape, fid):
length = shape.length
# I make sure it correctly calculated the lenght
if length == 0:
return 7000
if length >= 183 and length <= 185:
# I calculate the strike azimuth based on Trig and what the program has recorded the first and last point of each
# polyline to be
....
degreeBearing = a calculated number
# I next make the shapelyr feature layer out of my current intable(Zarza data), but only select the current object being
#calculated by using the where statement to select only the objct with the current FID
arcpy.MakeFeatureLayer_management(inTable, 'shapelyr', "{0} = {1}".format(fidField, str(fid)))
# I then make the PairedCheck6 feature layer out of my current intable(Zarza data), but excluding the current object being
#calculated by using the where statement to select only objects that do not match the current FID. This layer will be used
#to select the matching dip symble that belongs with the strike symbol for which the azimuth is being calculated
arcpy.MakeFeatureLayer_management(inTable, 'PairedCheck6', "{0} <> {1}".format(fidField, str(fid)))
#Next I Select the features from PairedCheck6 that are within a specified distance of the feature for which the azimuth
#is being calcualted
arcpy.SelectLayerByLocation_management('PairedCheck6', 'WITHIN_A_DISTANCE', 'shapelyr', '11 Meters')
# Next I create my curser object which I use to find the TrueCentroid and Length of each of the features Selected in PairedCheck6.
# Notice that only the selected objects in PairedCheck6 are used.
cursor = arcpy.da.SearchCursor('PairedCheck6',['SHAPE@TRUECENTROID', 'SHAPE@LENGTH'])
....
if isCentroidRight:
degreeBearing += 180
#returns the degreebearing value as the dip direction
return degreeBearing
else:
return 4000
cursor = arcpy.da.UpdateCursor(inTable, ['SHAPE@', 'FID', fieldName])
for row in cursor:
row[2] = Strike( row[0], row[1])
cursor.updateRow(row)
del cursor
Just a hunch but it may be choking on the space in "Murray SP2" (line 10 where you set the variable and then again in line 55 where your reference it) What kind of file is Murray SP2? does it need a file extension as well?
there seems to be a .gdb missing
'D:/Work/Everything/trial/Murray Sp2'
is trial the gdb? (ie trial.gdb) of is it a folder and Murray Sp2 a shapefile? (if the latter, it is missing a .shp). Don't use paths or anything with spaces either, you are just asking for trouble at some point)
You're going to want to wrap your path string in a r to make it "raw". Also, you have a dangling '/'. Please remove that, and the env setting (you're not using any of it's powers here) in line 6 and try again. Does that table actually exist?
# Set local variables
datasource = r"D:\Work\Everything\trial"
inTable = os.path.join(datasource,"Murray Sp2")
fieldName = "DipDir"
Thank you! The .shp seemed to open the file just fine. However, my problems have evolved slightly. The following error appeared on the right side (just Invalid expression "FID" = 2 on the left side).
ERROR 000358: Invalid expression "FID" = 2
Cannot acquire a lock.
Cannot acquire a lock.
Failed to execute (MakeFeatureLayer).
The program seems more concerned about the SQL expression at this point, but only does so if I use
inTable = os.path.join(datasource,"Murray Sp2.shp")
rather than
inTable = "Murray Sp2"
(I kept it, though inactive)
How are you running this script? You might want to copy snd paste it line by line into a python window and see where it chokes. Before you do, take a look at your shapefile and record FID = 2. You may also want to convert your data from a shapefile to a file gdb feature class. I don't have access to ArcGIS till Tuesday so I can't run your select statement to verify it; you could try a between statment....
I think what was happening was that my cursor was on my inTable, which for some reason prevented me from performing a query on it when creating feature layers from the inTable. I will create the layers before creating the cursor and try to just modify the feature layers afterwords. If it works I will post the results!
Ok, so I figured something out in the end. What I had mentioned just one post above did not work since the feature layer was still connected to the source data which had been locked by the UpdateCursor. Thus what I did was to use the CopyFeatures to create two new shape files and then edit them within my function using SelectLayerByAttribute. However, I found this code be be rather slow and inefficient, so I will be looking into a new way of doing this.
# Import system modules
import arcpy
import os
# Set local variables
datasource = r"C:\Alexsomewhere"
inTable = os.path.join(datasource, "Murray Sp2.shp")
fieldName = "DipDir"
arcpy.CopyFeatures_management(inTable, "C:\Alexsomewhere\shapelyr")
arcpy.CopyFeatures_management(inTable, "C:\Alexsomewhere\PairedCheck6")
def Strike(shape, fid):
# here I have cut out trigonometry that calculates a line direction. 55 is arbitrary and meaningless.
degreeBearing = 55
arcpy.SelectLayerByAttribute_management('shapelyr', 'NEW_SELECTION', "{0} = {1}".format("FID", fid))
arcpy.SelectLayerByAttribute_management('PairedCheck6', 'NEW_SELECTION', "{0} <> {1}".format("FID", fid))
#Next I Select the features from PairedCheck6 that are within a specified distance of the feature for which the azimuth is being calcualted
arcpy.SelectLayerByLocation_management('PairedCheck6', 'WITHIN_A_DISTANCE', 'shapelyr', '11 Meters', 'SUBSET_SELECTION')
# Next I create my curser object which I use to find the TrueCentroid and Length of each of the features Selected in PairedCheck6. Notice that only the selected objects in PairedCheck6 are used.
cursor = arcpy.da.SearchCursor('PairedCheck6',['SHAPE@TRUECENTROID', 'SHAPE@LENGTH'])
#Here I cut out logic to check that I have the correct number of selected rows from PairedCheck6, and if not, try to select the correct ones using their centroids and lengths.
#Once I have the correct number of other object(s) I create a pointgeometry and check its location relative to the current object then modify the degreeBearing that will be passed one last time depending on the result.
#returns the degreebearing value as the dip direction
return degreeBearing
with arcpy.da.UpdateCursor(inTable, ['SHAPE@', 'FID', fieldName]) as cursor:
for row in cursor:
row[2] = Strike( row[0], row[1])
cursor.updateRow(row)
del cursor
del row