Define a function in Tool Class of PYT

540
8
Jump to solution
04-22-2014 08:56 AM
JohnDye
Occasional Contributor III
I'm pretty sure this is possible and I'm just missing something relatively basic.

I wrote a little function to do something (proprietary) and I want to leverage it within the execute function of a Python Toolbox. For the sake of keeping the code tidy, I'd like to define it within the Tool Class rather than within the Execute Function of the Tool Class. like so:
def updateMessages(self, parameters):     """Modify the messages created by internal validation for each tool     parameter.  This method is called after internal validation."""     return  def MyFunction(inFeatureLayer):     arcpy.SelectLayerByAttribute_management(inFeatureLayer,  "NEW_SELECTION", '"ID" = ' + "'123456'")     SiteList = list(r[0] for r in arcpy.da.SearchCursor(inFeatureLayer, "ID"))     return SiteList  def execute(self, parameters, messages):     """The source code of the tool"""     inFeatureLayer = arcpy.parameters[0].valueAsText     Result = MyFunction(inFeatureLayer) # Why doesn???t this work???     # Do something with the result


When I do that however, the Execute function doesn't see it. The only way I can get the execute function to see my function is by defining it within the execute function, like so:
def updateMessages(self, parameters):         """Modify the messages created by internal validation for each tool         parameter.  This method is called after internal validation."""         return  def execute(self, parameters, messages):     """The source code of the tool"""     def MyFunction(inFeatureLayer):         arcpy.SelectLayerByAttribute_management(inFeatureLayer,  "NEW_SELECTION", '"ID" = ' + "'123456'")         SiteList = list(r[0] for r in arcpy.da.SearchCursor(inFeatureLayer, "ID")         return SiteList      inFeatureLayer = arcpy.parameters[0].valueAsText     Result = MyFunction(inFeatureLayer) # This works, but it seems more elegant to me if I could define it outside of Execute     # Do something with the result


This seems like it should be wholly possible. What I am doing wrong?
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
MathewCoyle
Frequent Contributor
You need to reference it using self. ToolClass is the name of your class and self is how the class is referenced when you are within that class.
 Result = self.MyFunction(inFeatureLayer)

I don't think there is anything in the .pyt format that would prevent this functionality but I have not tested this myself.

View solution in original post

0 Kudos
8 Replies
MathewCoyle
Frequent Contributor
You are trying to reference it at the class level without using self which won't work. You need to pass self to the function so the class can reference it, declare it within another function, or reference it outside the class.
0 Kudos
JohnDye
Occasional Contributor III
You are trying to reference it at the class level without using self which won't work. You need to pass self to the function so the class can reference it, declare it within another function, or reference it outside the class.


So do I just need to add self as the first parameter to the function like so?

MyFunction(self, param1, param2, param3):
    # Do stuff
0 Kudos
MathewCoyle
Frequent Contributor
Yes that should allow you to reference it within the class using self.
0 Kudos
JohnDye
Occasional Contributor III
Yes that should allow you to reference it within the class using self.


Sweet. Thanks Mat!
0 Kudos
JohnDye
Occasional Contributor III
So after I made the changes:
class Toolbox(object):
    def __init__(self):
        """Toolbox Initialization Settings"""
        self.label = "My Very Own Toolbox"
        self.alias = MVO_tbx"

        # List of the tools contained within the Toolbox
        self.tools = [ToolClass]

class ToolClass(object):
    def __init__(self):
        """Define the tool."""
        self.label = "MyTool"
        self.description = "No Description"
        self.canRunInBackground = True

    def getParameterInfo(self):
            """Establish the Parameters"""
            # Input Features Parameter
            param0 = arcpy.Parameter(
                displayName="Features",
                name="in_Features",
                datatype="GPFeatureLayer",
                parameterType="Required",
                direction="Input")
            param0.filter.list = ["Point"]

    def isLicensed(self):
        """Set whether tool is licensed to execute."""
        return True

    def updateParameters(self, parameters):
        """Modify the values and properties of parameters before internal
        validation is performed.  This method is called whenever a parameter
        has been changed."""
        return

    def updateMessages(self, parameters):
        """Modify the messages created by internal validation for each tool
        parameter.  This method is called after internal validation."""
        return

    def MyFunction(self, inFeatureLayer):
        arcpy.SelectLayerByAttribute_management(inFeatureLayer,  "NEW_SELECTION", '"ID" = ' + "'123456'")
        SiteList = list(r[0] for r in arcpy.da.SearchCursor(inFeatureLayer, "ID"))
        return SiteList

    def execute(self, parameters, messages):
        """The source code of the tool"""
        inFeatureLayer = arcpy.parameters[0].valueAsText
        Result = MyFunction(inFeatureLayer) # Why doesn�??t this work???
        # Do something with the result

When it gets to the method call in execute, I receive the error:
TypeError: unbound method �??MyFunction�?� must be called with �??ToolClass�?� instance as first argument (got Layer instead)

I've tried calling the method by referencing it via Class.method:
    def execute(self, parameters, messages):
            """The source code of the tool"""
            inFeatureLayer = arcpy.parameters[0].valueAsText
            Result = ToolClass.MyFunction(inFeatureLayer) # Why doesn�??t this work???
            # Do something with the result

Posts on StackOverflow seem to indicate that I need to instantiate the Class Objectand then call the Tool from the instance.

I'm not really sure how to do that.
0 Kudos
MathewCoyle
Frequent Contributor
You need to reference it using self. ToolClass is the name of your class and self is how the class is referenced when you are within that class.
 Result = self.MyFunction(inFeatureLayer)

I don't think there is anything in the .pyt format that would prevent this functionality but I have not tested this myself.
0 Kudos
JohnDye
Occasional Contributor III
You need to reference it using self. ToolClass is the name of your class and self is how the class is referenced when you are within that class.
 Result = self.MyFunction(inFeatureLayer)

I don't think there is anything in the .pyt format that would prevent this functionality but I have not tested this myself.


I reached out to Chris Fox earlier this morning and that was the exact answer he gave me. Makes total sense, thanks for posting. I knew it was something simple!
0 Kudos
TimBarnes
Occasional Contributor III
On a smilar vein, how do you do this within a arcpy.addin toolbar? (i.e. within a class?)
I've tried and tried and can't get it to work.

You define the function outside the onClick(self) but within the class right? And then how would you call it from within onClick(self)?

Edit- Never mind, got it 🙂
0 Kudos