Particularly with the release of ArcGIS 10.1 I have had a great deal of trouble with workspaces being locked within complex codes that are creating, reading from and writing to numerous feature classes and workspaces. These locks cause the code to fail intermittently at different places, although occasionally making it through without a problem.I have previously posted on this with a solution that sometimes helps reduce the problem, but is unable to eliminate it completely. That is using arcpy.Exists() and arcpy.Compact() in sequence upon the workspace. This combination of tools, when used in ArcGIS 10.0, seemed adequate, however it is no longer sufficient in 10.1 to prevent issues 100% of the time.In response to this I have developed a new method for clearing tricky locks which, for my purposes, works 100% of the time. It is a small function that can be added to the start of any arcpy script, and it requires the psutil Python library, which can be acquired here: http://code.google.com/p/psutil/. When using multiprocessing the code seems to work fine with the Parallel Python library, but will hang indefinitely if you are using the Multiprocessing library due to (I guess) the method in which child processes are spawned. However, the Parallel Python library has other issues, for example, I have had trouble with it when getting it to run checked out extensions such as Network Analyst.The following codeblock shows the necessary imports, the function block and an example of the usage.
import arcpy
import os
import psutil
def clearWSLocks(inputWS):
'''Attempts to clear ArcGIS/Arcpy locks on a workspace.
Two methods:
1: if ANOTHER process (i.e. ArcCatalog) has the workspace open, that process is terminated
2: if THIS process has the workspace open, it attempts to clear locks using arcpy.Exists, arcpy.Compact and arcpy.Exists in sequence
Notes:
1: does not work well with Python Multiprocessing
2: this will kill ArcMap or ArcCatalog if they are accessing the worspace, so SAVE YOUR WORK
Required imports: os, psutil
'''
# get process ID for this process (treated differently)
thisPID = os.getpid()
# normalise path
_inputWS = os.path.normpath(inputWS)
# get list of currently running Arc/Python processes
p_List = []
ps = psutil.process_iter()
for p in ps:
if ('Arc' in p.name) or ('python' in p.name):
p_List.append(p.pid)
# iterate through processes
for pid in p_List:
p = psutil.Process(pid)
# if any have the workspace open
if any(_inputWS in pth for pth in [fl.path for fl in p.get_open_files()]):
print ' !!! Workspace open: %s' % _inputWS
# terminate if it is another process
if pid != thisPID:
print ' !!! Terminating process: %s' % p.name
p.terminate()
else:
print ' !!! This process has workspace open...'
# if this process has workspace open, keep trying while it is open...
while any(_inputWS in pth for pth in [fl.path for fl in psutil.Process(thisPID).get_open_files()]):
print ' !!! Trying Exists, Compact, Exists to clear locks: %s' % all([arcpy.Exists(_inputWS), arcpy.Compact_management(_inputWS), arcpy.Exists(_inputWS)])
return True
#######################################
## clearWSLocks usage example #########
#######################################
# define paths and names
workspace = 'C:\\Temp\\test.gdb'
tableName = 'testTable'
# create table
arcpy.CreateTable_management(workspace, tableName)
# usage of clearWSLocks
clearWSLocks(workspace)
I have also attached the code as a separate module (clearWSLocks.py), which can be used in the following fashion:
import arcpy
import clearWSLocks
# define paths and names
workspace = 'C:\\Temp\\test.gdb'
tableName = 'testTable'
# create table
arcpy.CreateTable_management(workspace, tableName)
# usage of clearWSLocks
clearWSLocks.clear(workspace)