4

I've written a python script that uses a Spatial Analyst function and hence requires the Spatial Analyst extension to be enabled. I would like to be able to check out the extension only if it hasn't already been manually checked out by the user (i.e. via the "Customize->Extensions" dialog).

There doesn't seem to be any way of testing whether the extension is already checked out out using arcpy.CheckExtension as that returns Available regardless of whether a license is already checked out or not (assuming there is a license available).

My code can check out the extension and then check it back in easily enough which is fine if the code is running outside of ArcGIS. However, this causes an issue in ArcGIS if a user has already checked the extension out manually via the "Customize->Extensions" dialog as they will suddenly start getting the "ERROR 000824: The tool is not licensed" or "ERROR 010096: There is no Spatial Analyst license currently available or enabled." errors when trying to use other Spatial Analyst tools/functions (as my code has checked the extension back in).

A further complication that may confuse the user is that when they open the "Customize->Extensions" dialog to check if the SA extension is checked out, the tick will still be in the extensions check box as checking the extension in via code does not update the dialog. E.g see screenshot below

enter image description here

My work around was to test using a simple spatial analyst tool (Int(1)) in a try:except: clause (see below), but that's just ugly.

from arcpy.sa import Int

def sa_is_licensed():
    try:
        Int(1)
        return True
    except (ExecuteError, RuntimeError) as e:
        # "ERROR 000824: The tool is not licensed"
        # "ERROR 010096:  There is no Spatial Analyst license currently available or enabled."
        if 'ERROR 000824' in e.message or 'ERROR 010096' in e.message:
            if arcpy.CheckExtension('Spatial') == 'Available' and arcpy.CheckOutExtension('Spatial')=='CheckedOut':
               return False
            else:raise
        else:raise

already_licensed = sa_is_licensed()

# My big long script...

if not already_licensed: arcpy.CheckInExtension('Spatial')

Are there any better ways to check from ArcPy if an ArcGIS extension has already been checked out?

  • I'd like to know that too. Normally you can check your product which says 'yes' if the product is available then check out and check in when finished but this will not tell you if you've already got the license activated. – Michael Stimson Feb 10 '15 at 22:44
  • I don't think so. The code sample from Esri on the help page for arcpy.CheckInExtension() uses a try and except LicenseError approach. – dmahr Feb 10 '15 at 22:49
  • Yes, something analogous to arcpy.CheckProduct(product)=='AlreadyInitalized', but for extensions, not just desktop (arcview/arceditor/arcinfo/etc.) licenses would be good. – user2856 Feb 10 '15 at 22:51
  • 1
    @MichaelMiles-Stimson, yes arcpy.sa.Int. Trying to use that without checking out an SA license will raise an exception. No, if you're running your script "in-process" or as a python add-in, if an extension is checked out manually, you don't need to check it out in code. – user2856 Feb 11 '15 at 2:36
  • 1
    @MichaelMiles-Stimson if you are writing a python toolbox (pyt), you can test for extension/license level in the isLicensed(self) method of your Tool class. If you return False, ArcToolbox/Catalog will display a lock icon overlaid on the tool icon. – user2856 Feb 12 '15 at 23:28
4

This can be done with python, but not using arcpy as far as I know. If you use comtypes you can have some degree of access to ArcObjects. By accessing the AoInitialize class, you can check on licenses/extensions that are checked out by supplying an extension code.

Here is some sample code:

import comtypes

# load olb
esriSys = r'C:\Program Files (x86)\ArcGIS\Desktop10.3\com\esriSystem.olb'
comtypes.client.GetModule(esriSys)
import comtypes.gen.esriSystem as esriSystem


def NewObj(COMClass, COMInterface):
    """Creates a new comtypes POINTER object where\n\
    MyClass is the class to be instantiated,\n\
    MyInterface is the interface to be assigned"""
    from comtypes.client import CreateObject
    try:
        ptr = CreateObject(COMClass, interface=COMInterface)
        return ptr
    except:
        return None

# now call AoInitialize
pInit = NewObj(esriSystem.AoInitialize,
                esriSystem.IAoInitialize)

# 10 is spatial analyst
licenseAvailable = pInit.IsExtensionCheckedOut(10)
if licenseAvailable:
    print 'license is checked out'
else:
    print 'license not checked out'

And here is an example inside ArcMap (I have taken the Snippets module and modified it a bit and saved it as a package called "arcobjects"). Also, I did not mean to make this confusing, but my variable name is misleading...It should have been called licenseCheckedOut, as that is the actual property being used, not checking for availability (which you can do in arcpy).

usage with license checked out:

enter image description here

And once the extension is checked back in:

enter image description here

  • 1
    I forgot to add this DOES NOT work in stand alone, but if the user is running as a script tool it should work as expected. – crmackey Feb 11 '15 at 4:03
  • Any reason it doesn't work standalone? I've got a few comtypes/ArcObjects scripts that run standalone as long as ArcObjects is initialised properly. – user2856 Feb 11 '15 at 6:54
  • 1
    Yep, works fine standalone. Just need to call pInit.Initialize(product_code) before anything else to set your basic/standard/advanced license level. i.e. pInit.Initialize(esriSystem.esriLicenseProductCodeBasic) – user2856 Feb 12 '15 at 0:02
  • 2
    Since no-one else has answered, I'm going to mark this as correct even though I asked for an arcpy solution (and I don't want to go to the effort of shipping the comtypes package with my add-ins/tools) as it looks to be the only other way of testing if an extension has been checked out apart from a try/except. – user2856 Feb 14 '15 at 21:50
  • 2
    Submitted as an "ArcGIS Idea" – user2856 Mar 6 '15 at 23:14
1

This can be made a bit more "pythonic" with a context manager:

import arcview, arcpy

class Spatial(object):
    '''Context manager for the ArcGIS Spatial Analyst Extension'''
    def __init__(self):
        self.name = 'Spatial'
        from arcpy.sa import Int

        try:
            Int(1)
            self.checkedout = True
        except RuntimeError:
            self.checkedout = False

    def checkin(self):
        if self.checkedout: 
            return
        else:
            arcpy.CheckInExtension(self.name)

    def checkout(self):
        if self.checkedout: 
            return

        if arcpy.CheckExtension(self.name) == "Available":
            arcpy.CheckOutExtension(self.name)
        else:
            raise RuntimeError("%s license isn't available" % self.name)

    def __enter__(self):
        self.checkout()

    def __exit__(self, *args):
        self.checkin()


if __name__ == '__main__':
    from arcpy.sa import Int
    with Spatial():
        a = Int(2)
        print repr(a)

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.