I am writing a Python tool that perform heavy tasks in a loop. When the user clicks "Close" I want to break the loop, perform some cleanup, and then finish.
Consider this example tool that counts down from ten:
import arcpy
import time
class Tool(object):
def __init__(self):
self.label = "Cancel Test"
self.description = "Tests how the cancel function works."
self.canRunInBackground = False
def execute(self, parameters, messages):
for i in range(10, -1, -1):
arcpy.AddMessage(i)
time.sleep(1)
arcpy.AddMessage("We have lift-off!")
return
When I click "Close" in the beginning of the execution it does not brake the loop or give me an opportunity to perform any clean up. Instead it loops to the very end and adds the message "We have lift-off!"
before it outputs this:
Completed script CancelTest...
Cancelled function
(CancelTest) aborted by User.
Failed at [TIME] (Elapsed Time: 10,01 seconds)
I have found documentation for ArcGIS Pro (that uses Python 3.4) that describes how you can do this there using isCancelled
:
import arcpy
import time
#Make sure it does not auto cancel.
arcpy.env.autoCancelling = False
class Tool(object):
def __init__(self):
self.label = "Cancel Test"
self.description = "Tests how the cancel function works."
self.canRunInBackground = False
def execute(self, parameters, messages):
for i in range(10, -1, -1):
arcpy.AddMessage(i)
time.sleep(1)
#Check if the user clicked "Close"
if arcpy.env.isCancelled:
arcpy.AddMessage("Launch aborted!")
return
arcpy.AddMessage("We have lift-off!")
return
However, when I run this from ArcCatalog 10.3 (i.e. not using ArcGIS Pro) it gives me the following error:
Traceback (most recent call last):
File "H:\Mina Dokument\DGD\Python\CancelTest.py", line 19, in execute
if arcpy.env.isCancelled:
AttributeError: 'GPEnvironment' object has no attribute 'isCancelled'
Is there anyway to mimic the behavior that is available in ArcGIS Pro in an ordinary Python toolbox using Python 2.7?
Best Answer
Farid Cher's answer is partially correct.
You can use the Progressor to 'catch' a cancel event from within a Python script, and you can also do whatever cleanup necessary as well, if you enclose the call within a
try ... except
clause.For example, a python toolbox:
This allows the user to run the tool:
And then cancel, which is handled gracefully (and still counted as a failed run):
edit: This doesn't appear to work with 10.3 or ArcGIS Pro.
To catch the cancels (tested in ArcGIS Pro), we bring back our good friend
arcgisscripting
. This is similar to catching the cancel from the progressor, but the entire execute function, or at least the majority of it, needs to be inside thetry
: