2

I am trying to understand how ArcGIS adds layers and the problems involved with repeated calls to an Arc Python tool to which a script is attached (ArcMap 10.5). I created a stripped down (no parameters) script that opens an input file, creates a minumum elevation raster with focal statistics and then adds the result to the open map.

# Import arcpy module
import arcpy
from arcpy import env
from arcpy.sa import *

Check out the ArcGIS Spatial Analyst extension license

arcpy.CheckOutExtension("Spatial")

mxd = arcpy.mapping.MapDocument("CURRENT") df = arcpy.mapping.ListDataFrames(mxd)[0] arcpy.AddMessage ("Version 1.0: Got Data Frame "+df.name)

env.workspace = "C:/ArcGIS" env.overwriteOutput = True

Local variables:

Min_Elev = "" Max_Elev = ""

Process: Min - Focal Statistics

neighborhood = "Circle 3 CELL" arcpy.AddMessage ("Neighborhood is "+neighborhood)

inRaster = "kom_dsm_lidar.tif" Min_elev_out = "c:/ArcGIS/Tst_MinElev.tif" outRaster_lyr_name = "MinElev.lyr"

arcpy.Delete_management(Min_elev_out) arcpy.Delete_management(outRaster_lyr_name)

Execute Min FocalStatistics&save

Min_Elev = FocalStatistics(inRaster, neighborhood, "MINIMUM","DATA") Min_Elev.save(Min_elev_out)

Min_Elev_lyr = arcpy.MakeRasterLayer_management (Min_Elev, "Min_Elev") arcpy.SaveToLayerFile_management(Min_Elev_lyr,outRaster_lyr_name) arcpy.AddMessage ("Layer Created")

out_lyr = arcpy.mapping.Layer(r"C:/ArcGIS/MinElev.lyr") arcpy.AddMessage ("Beginning raster add") arcpy.mapping.AddLayer(df, out_lyr, "BOTTOM")

arcpy.RefreshActiveView() arcpy.RefreshTOC()

arcpy.AddMessage ("Processing Complete")

When I run the tool first time, no problem, second time, no problem, but the third time I get the following error:

Traceback (most recent call last): File "C:\ArcGIS\Add-Ins\Test_create_and_add_layer2.py", line 31, in Min_Elev.save(Min_elev_out) RuntimeError: ERROR 000871: C:\ArcGIS\Tst_MinElev.tif: Unable to delete the output ????????????.

I gather this is a file locking problem since I can't delete the output .tif file unless I exit the current map and then delete it. (Just closing Python isn't sufficient.) If I again reload the map, after deleting the output .tif, I can execute the tool twice successfully, but it always fails on the third try. If I don't delete it, it fails immediately.

I also tried adding two delete statements:

arcpy.Delete_management(Min_elev_out)
arcpy.Delete_management(outRaster_lyr_name)

but if the output files already exist, the deletes fail.

My question is how can I check whether potential output files are locked and if so, how can I unlock them prior to overwriting them? I want to do this from within the Python program, not by using Windows (as some of the replies to previous versions of this question suggestion). There are other similar versions of this question on S.E., but none of the answers directly answer the question.

Also not sure why the third iteration fails, but not the second. There must be a solution for ArcMap.

Vince
  • 20,017
  • 15
  • 45
  • 64
William
  • 149
  • 9
  • Maybe some clues here: https://community.esri.com/t5/arcobjects-sdk-questions/releasing-locks-on-raster-objects/td-p/604437 and then here: https://gis.stackexchange.com/questions/80/accessing-arcobjects-from-python – GBG Jun 02 '22 at 18:33
  • Thanks for replying. I'm not sure how your second link relates to the problem, though. – William Jun 03 '22 at 20:41
  • It would appear that braking the lock links being held on raster data in ArcGIS is only solvable using ArcObjects. You would need to figure out some way to access ArcObjects in your Python script to accomplish that task. – GBG Jun 03 '22 at 22:13

1 Answers1

1

A variable that references a layer file on disk will place a lock on the (.lyr) file. It is good practice to remove the object reference using the Python del command at the end of a script or within a Python try/except statement.

Layers opened in the MXD also have a lock. So try removing the layer from the mxd before deleting.

arcpy.mapping.RemoveLayer(df, out_lyr)
arcpy.RefreshActiveView()
mxd.save()
Mark Bryant
  • 1,435
  • 8
  • 7