python toolbox Feature Set output parameter

4548
7
05-28-2013 11:12 AM
CharlesArnold
New Contributor III
I'm having trouble setting an output parameter of type "Feature Set" in a python toolbox.  Here's what I have currently:

import arcpy

class Toolbox(object):
    def __init__(self):
        
        self.label = "FeatureSet Output Test"
        self.alias = ""
        self.tools = [Test]

class Test(object):
    
    def __init__(self):
        
        self.label = "Test1"
        self.description = "Output a few points in a feature set"
        self.canRunInBackground = False

    def getParameterInfo(self):
        
        params = []
        
        param0 = arcpy.Parameter(
            displayName = "FS Output", name = "fsOutput",
            datatype = "Feature Set", parameterType = "Derived", direction = "Output")
        params.append(param0)
        
        param1 = arcpy.Parameter(
            displayName = "JSON Output", name = "strOutput",
            datatype = "String", parameterType = "Derived", direction = "Output")
        params.append(param1)
        
        return params

    def execute(self, parameters, messages):
        
        gdbPath = 'in_memory'
        featureClassName = 'points'
        featureClass = '{}/{}'.format(gdbPath, featureClassName)
        
        try:
            arcpy.AddMessage('Creating a point feature class with 1 text attribute')
            
            if arcpy.Exists(featureClass):
                arcpy.Delete_management(featureClass)
            
            arcpy.CreateFeatureclass_management(
                out_path=gdbPath, out_name=featureClassName, geometry_type='POINT',
                spatial_reference=arcpy.SpatialReference(4326))
            
            arcpy.AddField_management(
                in_table=featureClass,
                field_name='Attribute1', field_type='TEXT')
            
            arcpy.AddMessage('Inserting a couple points')
            with arcpy.da.InsertCursor(featureClass, ('SHAPE@XY', 'Attribute1')) as cur:
                cur.insertRow(((1, 1), 'point at 1, 1'))
                cur.insertRow(((2, 2), 'point at 2, 2'))
            
            arcpy.AddMessage('Setting the output parameters')
            featureSet = arcpy.FeatureSet(featureClass)
            parameters[0].value = featureSet
            parameters[1].value = featureSet.JSON                
        
        except Exception as e:
            arcpy.AddError(str(e))


The first output parameter displays as "empty"; if I print paramers[0].value it will output "None" ..

The second TEXT parameter seems to work fine; I get the following output:
{"displayFieldName":"","fieldAliases":{"OID":"OID","Attribute1":"Attribute1"},"geometryType":"esriGeometryPoint","spatialReference":{"wkid":4326,"latestWkid":4326},"fields":[{"name":"OID","type":"esriFieldTypeOID","alias":"OID"},{"name":"Attribute1","type":"esriFieldTypeString","alias":"Attribute1"}],"features":[{"attributes":{"OID":1,"Attribute1":"point at 1, 1"},"geometry":{"x":1.0000000000000568,"y":1.0000000000000568}},{"attributes":{"OID":2,"Attribute1":"point at 2, 2"},"geometry":{"x":2.0000000000000568,"y":2.0000000000000568}}]}


Anyone know why this doesn't work?

Thanks in advance 🙂
Tags (2)
0 Kudos
7 Replies
JeanBissonnette
New Contributor III
Hi

I had the same problem as yours

To Resolve, I used the following parameter: GPFeatureRecordSetLayer

maybe it can solve your problem:

param0 = arcpy.Parameter(
            displayName = "FS Output", name = "fsOutput",
            datatype = "GPFeatureRecordSetLayer", parameterType = "Derived", direction = "Intput")


Jean
0 Kudos
CharlesArnold
New Contributor III
Thanks for your suggestion; interesting that it fixes it for you.  Are you using 10.1 SP1?
Testing on my side with the following code, the problem persists.
import arcpy

class Toolbox(object):
    def __init__(self):
        
        self.label = "FeatureSet Output Test"
        self.alias = ""
        self.tools = [Test]

class Test(object):
    
    def __init__(self):
        
        self.label = "Test1"
        self.description = "Output a few points in a feature set"
        self.canRunInBackground = False

    def getParameterInfo(self):
        
        params = []
        
        param0 = arcpy.Parameter(
            displayName = "FS Output", name = "fsOutput",
            datatype = "Feature Set", parameterType = "Derived", direction = "Output")
        params.append(param0)
        
        param1 = arcpy.Parameter(
            displayName = "FS Output1", name = "fsOutput1",
            datatype = "GPFeatureRecordSetLayer", parameterType = "Derived", direction = "Input")
        params.append(param1)
        
        param2 = arcpy.Parameter(
            displayName = "FS Output2", name = "fsOutput2",
            datatype = "GPFeatureRecordSetLayer", parameterType = "Derived", direction = "Output")
        params.append(param2)
        
        param3 = arcpy.Parameter(
            displayName = "JSON Output", name = "strOutput",
            datatype = "String", parameterType = "Derived", direction = "Output")
        params.append(param3)
        
        return params

    def execute(self, parameters, messages):
        
        gdbPath = 'in_memory'
        featureClassName = 'points'
        featureClass = '{}/{}'.format(gdbPath, featureClassName)
        
        try:
            arcpy.AddMessage('Creating a point feature class with 1 text attribute')
            
            if arcpy.Exists(featureClass):
                arcpy.Delete_management(featureClass)
            
            arcpy.CreateFeatureclass_management(
                out_path=gdbPath, out_name=featureClassName, geometry_type='POINT',
                spatial_reference=arcpy.SpatialReference(4326))
            
            arcpy.AddField_management(
                in_table=featureClass,
                field_name='Attribute1', field_type='TEXT')
            
            arcpy.AddMessage('Inserting a couple points')
            with arcpy.da.InsertCursor(featureClass, ('SHAPE@XY', 'Attribute1')) as cur:
                cur.insertRow(((1, 1), 'point at 1, 1'))
                cur.insertRow(((2, 2), 'point at 2, 2'))
            
            arcpy.AddMessage('Setting the output parameters')
            featureSet = arcpy.FeatureSet(featureClass)
            parameters[0].value = featureSet
            parameters[1].value = featureSet
            parameters[2].value = featureSet
            parameters[3].value = featureSet.JSON                
        
        except Exception as e:
            arcpy.AddError(str(e))


Results window after running that script:
[ATTACH=CONFIG]24773[/ATTACH]

Hi

I had the same problem as yours

To Resolve, I used the following parameter: GPFeatureRecordSetLayer

maybe it can solve your problem:

param0 = arcpy.Parameter(
            displayName = "FS Output", name = "fsOutput",
            datatype = "GPFeatureRecordSetLayer", parameterType = "Derived", direction = "Intput")


Jean
0 Kudos
CharlesArnold
New Contributor III
Can you paste in the contents of your .pyt that works?

Hi

I had the same problem as yours

To Resolve, I used the following parameter: GPFeatureRecordSetLayer

maybe it can solve your problem:

param0 = arcpy.Parameter(
            displayName = "FS Output", name = "fsOutput",
            datatype = "GPFeatureRecordSetLayer", parameterType = "Derived", direction = "Intput")


Jean
0 Kudos
JeanBissonnette
New Contributor III
Yes, I use 10.1 SP1

the datatype = "Feature Set" in param0 is the bad parameter. For the Feature Set use GPFeatureRecordSetLayer parameter.

Unlike my first response, the direction parameter can be output «direction="Output"»


Jean
0 Kudos
CharlesArnold
New Contributor III
param2 in the example script is setup exactly like you say; param0, param1 and param2 all don't work.  If I setup the script to not have the other parameters, so it's like the first example but with datatype="GPFeatureRecordSetLayer", it still doesn't work.

Do you have an actual script that can be ran that will show your suggestion works?

Yes, I use 10.1 SP1

the datatype = "Feature Set" in param0 is the bad parameter. For the Feature Set use GPFeatureRecordSetLayer parameter.

Unlike my first response, the direction parameter can be output «direction="Output"»


Jean
0 Kudos
KevinHibma
Esri Regular Contributor
What exactly is it you're trying to do?
I dont normally see people using FeatureSet as output as FeatureClass usually is sufficient.

If you're ultimately trying to make a GP Service, I'd just stick with FC for output, and FS for input.

I dont know if this will help, but if you want to stick with FS as output, maybe try doing a load.
For example
feature_class = "....the FC you've created..."
feature_set = arcpy.FeatureSet()
feature_set.load(feature_class)
0 Kudos
CharlesArnold
New Contributor III
While using the featureSet.load method doesn't change the behavior, using 'Feature Class' does indeed work as expected! I was using a FeatureSet simply because that's what the existing code, using the classic .tbx toolbox used, and it worked fine.

What's the real difference between FeatureSet and FeatureClass?  Is it just that the parameter-input user interface behaves differently for input parameters of a FeatureSet vs FeatureClass?  Nothing in the documentation really jumped out at me that said "Feature Sets are not meant to be used for output parameters" .. on the contrary, the documentation at http://resources.arcgis.com/en/help/main/10.1/index.html#//00170000009n000000 says:

Note:

Server tools communicate using feature sets and record sets, meaning data must be created using or loaded into these objects when using server tools.


What I'm working on does end up being a GP Task published on ArcGIS Server.  I can call the task and retrieve the output as a FeatureClass without issue, but FeatureSet fails silently.  Is there any difference, good or bad, when using FeatureSet vs FeatureClass as an output from a classic .tbx, where it does work?


What exactly is it you're trying to do?
I dont normally see people using FeatureSet as output as FeatureClass usually is sufficient.

If you're ultimately trying to make a GP Service, I'd just stick with FC for output, and FS for input.

I dont know if this will help, but if you want to stick with FS as output, maybe try doing a load.
For example
feature_class = "....the FC you've created..."
feature_set = arcpy.FeatureSet()
feature_set.load(feature_class)