-1

I am using ArcGIS 10.4.1.5686 and running code within ArcMap. I thought that this question is similar to SQL query new feature with loop, or even Using a for loop to execute a query in arcpy, but neither can seem to help me. My issue is that when I try to SQL query when creating a new feature layer (MakeFeatureLayer) within a definition within a for loop, the SQL expression is considered invalid. I get the following error.

ERROR 000358: Invalid expression "FID" = 0 Cannot acquire a lock. Cannot acquire a lock. Failed to execute (MakeFeatureLayer)

This is my code snipet. I have also tried str(fid) within the where clause.

# Import system modules
import arcpy
import os


# Set local variables
datasource = r"C:/Alexsomeplace"
inTable = os.path.join(datasource, "Murray Sp2.shp")
fieldName = "DipDir"
fidField = arcpy.AddFieldDelimiters(datasource, "FID")

def Strike(shape, fid):

    # here I have cut out trigonometry that calculates a line direction. 55 is arbitrary and meaningless. 
    degreeBearing = 55

    arcpy.MakeFeatureLayer_management(inTable, 'shapelyr', "{0} = {1}".format(fidField, fid))

    arcpy.MakeFeatureLayer_management(inTable, 'PairedCheck6', "{0} <> {1}".format(fidField, 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'])

    #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.

    arcpy.Delete_management('shapelyr')
    arcpy.Delete_management('PairedCheck6')     
    #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

Another thing to mention is that I thought that perhaps the cursor was interfering with the SQL query while it was on top of the inTable. However, I rearragned the code so that I MadeFeatureLayer outside of the Strike def (where the SQL does work if I apply it), and instead use my SQL inside the Strike definition by using SelectLayerByAttribute_management. However, again the expression is invalid.

ERROR 000358: Invalid expression Cannot acquire a lock. Cannot acquire a lock. Failed to execute (SelectLayerByAttribute).

arcpy.MakeFeatureLayer_management(inTable, 'shapelyr')

def Strike(shape, fid):

    degreeBearing = 55

    arcpy.SelectLayerByAttribute_management('shapelyr', 'NEW_SELECTION', "{0} = {1}".format("FID", fid))

    arcpy.Delete_management('shapelyr')

    #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)
  • 1
    FIrst off, ArcGIS 10.1 is rather old, and most people here using ArcGIS are way beyond that release (which is retired from support), so it would be difficult to reproduce your issue. But the problem could be due to having the feature class (or its feature dataset, if the FC is in one) open in ArcCatalog on the same host (or some other host), so you need to be researching lock issues, not ArcPy, per se. Please Edit the question to assert the exact 10.1 release (you should be at 10.1sp1 with 26-28 patches). – Vince Jan 20 '18 at 22:19
  • Your code doesn't make sense to me. You set a variable value, then create a layer, then delete the layer, then pass the variable value back. What is the Make Feature Layer for? Why are you trying to select just taht feature? What are you actually trying to do with your code? – Midavalo Jan 21 '18 at 1:00
  • I too see no need for the MakeFeatureLayer or SelectLayerByAttribute here. Have you tried just using a where_clause as part of opening your update cursor? – PolyGeo Jan 21 '18 at 2:26
  • @Midavalo I have grossly simplified my code for personal diagnosis reasons and to try to only keep the broken components. I will edit in a bit to add some clarification, but I originally have over a hundred lines within the definition. A simplified explanation would be that I calculate a degree bearing using trigonometry, then for each object of a given length within table, I try to spatially find a single matching object within the same table in order to then check that object's location relative to the current row. Based on that final relation, I modify the final degree bearing output. – Alexander Audet Jan 21 '18 at 2:47
  • @Vince It appears that my ArcGIS was updated within the last few weeks to 10.4. – Alexander Audet Jan 21 '18 at 3:37
1

I now know that the UpdateCursor puts a lock on my inTable that would be effective when I later try to perform MakeFeatureLayer.

The UpdateCursor is a cursor object that allows for the update or deletion of rows in a feature class or table. The cursor will place a lock on the data that will persist until the object is deleted or when the script terminates.

My theory is that even when I perform MakeFeatureLayer before the existence of a cursor, that it is connected to my inTable and thus also becomes locked by the UpdateCursor. This is supported by the fact that when you look at the location of a feature class, it shares the same shapefile as the source shapefile it was created from.

Thus I had to create an entirely new set of shapefiles using CopyFeatures to get around the problem (just need to figure out how to permanently delete them for file management). Then my program seems to work just fine.

Here is my full working snippet for future reference.

# 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')

    # 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

If the relationship between a source file and a created feature class is suppose to be common knowledge, it is woefully underrepresented in the ArcGIS literature. I discovered it after reading about feature classes several times only after noticing that I never had to give my feature classes a file directory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.