Select to view content in your preferred language

ArcGIS API for Python - FeatureSet.save() Error

684
7
Jump to solution
03-26-2025 11:28 AM
ewmahaffey
Occasional Contributor

I'm trying to use the ArcGIS API for Python without ArcPy. I've written a basic script that connects to a WFS, creates a FeatureLayer, then FeatureSet. I then tried to use the FeatureSet.save() function to simply save the data to a local Shapefile. When I run the script (in the Idle IDE), I get an error saying: "ImportError: ArcPy is required to export a feature class".  From a few other threads that I've read, I should be able to run this without ArcPy. Any thoughts?

from arcgis.features import FeatureLayer
from arcgis.features import FeatureSet

hurricaneDir = r'C:/Workspace/Temp'
PastTracksURL = 'https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/Active_Hurricanes_Sampler/FeatureServer/3'

feature_layer = FeatureLayer(PastTracksURL)
feature_set = feature_layer.query(out_fields='*')

feature_set.save(hurricaneDir, "PastTracks_Temp_Data.shp")
print ("WFS Data Successfully Saved as a Shapefile")
Python 3.11.2 (tags/v3.11.2:878ead1, Feb  7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.

======= RESTART: C:\Workspace\Temp\WFS_to_FeatureClass_forEsriSupport.py =======
Traceback (most recent call last):
  File "C:\Workspace\Temp\WFS_to_FeatureClass_forEsriSupport.py", line 10, in <module>
    feature_set.save(hurricaneDir, "PastTracks_Temp_Data.shp")
  File "C:\Workspace\Python_Virtual_Environment\Lib\site-packages\arcgis\features\feature.py", line 1409, in save
    raise ImportError("ArcPy is required to export a feature class.")
ImportError: ArcPy is required to export a feature class.

Results

 

0 Kudos
1 Solution

Accepted Solutions
ewmahaffey
Occasional Contributor

Although I wasn't able to get the FeatureSet.save() function to work like the API Reference guide said it would.  I kept getting the "ImportError: ArcPy is required to export a feature class" error.  Here's the final script in case anyone needs it.

from arcgis.features import FeatureLayer
from arcgis.features import FeatureSet

## the filepath for the output shapefile
hurricane_shp = r'C:/Workspace/Temp/PastTracks_Temp_Data.shp'

## the url to the feature layer
PastTracksURL = 'https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/Active_Hurricanes_Sampler/FeatureServer/2'
#PastTracksURL = 'https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/Active_Hurricanes_v1/FeatureServer/3'

## create FeatureLayer object
feature_layer = FeatureLayer(PastTracksURL)

df = feature_layer.query(where = "Shape__Length is not null", out_fields = "*", return_geometry=True).sdf
print (df)

## export to shapefile
df.spatial.to_featureclass(hurricane_shp)

print ("Done")

 

View solution in original post

7 Replies
CodyPatterson
MVP Regular Contributor

Hey @ewmahaffey 

You may be able to use geopandas to save as a Shapefile is this here is giving you some issues:

from arcgis.features import FeatureLayer
from arcgis.features import FeatureSet
import geopandas as gpd
import json

hurricaneDir = r'C:/Workspace/Temp'
PastTracksURL = 'https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/Active_Hurricanes_Sampler/FeatureServer/3'

feature_layer = FeatureLayer(PastTracksURL)
feature_set = feature_layer.query(out_fields='*')

geojson_str = feature_set.to_geojson
gdf = gpd.read_file(json.dumps(json.loads(geojson_str)))

output_shp = hurricaneDir + '/PastTracks_Temp_Data.shp'
gdf.to_file(output_shp)
# Here you may need to_file like this: to_file(output_shp, driver='ESRI Shapefile')

print("WFS Data Successfully Saved as a Shapefile")

I haven't used this method in quite a long time, you might need to try a couple different conversions out!

Cody

ewmahaffey
Occasional Contributor

Thanks Cody.  I've tried using Pandas GDFs and SDFs but haven't had much luck. One thing I did notice was that this code would work for a WFS that has point data, but not a WFS with polylines

feature_set.sdf.spatial.to_featureclass(PastTracks_Temp_Output, overwrite=True)

I tried running your code sample and got a KeyError 

KeyError: 'geometry'

 

0 Kudos
Clubdebambos
MVP Regular Contributor

Hi @ewmahaffey,

Give this a whirl. While this works for me, it could be that I have access to ArcPy, so it would be interesting to see if it works in your environment,

from arcgis.features import GeoAccessor
from arcgis.features import FeatureLayer

## the filepath for the output shapefile
hurricane_shp = r'C:/Workspace/Temp/PastTracks_Temp_Data.shp'

## the url to the feature layer
PastTracksURL = 'https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/Active_Hurricanes_Sampler/FeatureServer/3'

## create FeatureLayer object
feature_layer = FeatureLayer(PastTracksURL)

## convert to df
df = GeoAccessor.from_layer(feature_layer)

## export to shapefile
df.spatial.to_featureclass(hurricane_shp)

 

Please let us know. 

All the best,

Glen

 

~ learn.finaldraftmapping.com
0 Kudos
ewmahaffey
Occasional Contributor

Thanks Glen. I ran your code in my Python VENV and I'm getting a similar error message that I received when I was testing the use of SDFs and GDFs. It seems like I need to define the geometry type or something.  From I can tell it thinks the geometry is in polygon format even though it's polylines, and no results come back. It's so strange

Python 3.11.2 (tags/v3.11.2:878ead1, Feb  7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.

= RESTART: C:/Workspace/Temp/WFS_to_FeatureClass_forEsriSupport_wGeoAccessor.py
Traceback (most recent call last):
  File "C:/Workspace/Temp/WFS_to_FeatureClass_forEsriSupport_wGeoAccessor.py", line 17, in <module>
    df.spatial.to_featureclass(hurricane_shp)
  File "C:\Workspace\Python_Virtual_Environment\Lib\site-packages\arcgis\features\geo\_accessor.py", line 2107, in to_featureclass
    result = to_featureclass(
  File "C:\Workspace\Python_Virtual_Environment\Lib\site-packages\arcgis\features\geo\_io\fileops.py", line 1297, in to_featureclass
    res = _pyshp2(df=df, out_path=out_location, out_name=fc_name)
  File "C:\Workspace\Python_Virtual_Environment\Lib\site-packages\arcgis\features\geo\_io\fileops.py", line 1510, in _pyshp2
    if geom.type == "Polygon":
AttributeError: 'NoneType' object has no attribute 'type'

 

0 Kudos
ewmahaffey
Occasional Contributor

OK, so we discovered that the code is actually correct, but the backend service has data integrity errors. Which is unfortunate.  There is a record that does not have a geometry value, that causes errors. 

ewmahaffey_0-1743089229819.png

I tested a couple of the other layers coming from this service, and found a similar issue. However, I tested layers from https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/Active_Hurricanes_v1/FeatureServe... and it works fine. I hope this helps someone else who might stumble upon this. Maybe the data will get fixed in the "Active_Hurricanes_Sampler" service.  For now I just plan to query out the Null records.

0 Kudos
ewmahaffey
Occasional Contributor

Although I wasn't able to get the FeatureSet.save() function to work like the API Reference guide said it would.  I kept getting the "ImportError: ArcPy is required to export a feature class" error.  Here's the final script in case anyone needs it.

from arcgis.features import FeatureLayer
from arcgis.features import FeatureSet

## the filepath for the output shapefile
hurricane_shp = r'C:/Workspace/Temp/PastTracks_Temp_Data.shp'

## the url to the feature layer
PastTracksURL = 'https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/Active_Hurricanes_Sampler/FeatureServer/2'
#PastTracksURL = 'https://services9.arcgis.com/RHVPKKiFTONKtxq3/arcgis/rest/services/Active_Hurricanes_v1/FeatureServer/3'

## create FeatureLayer object
feature_layer = FeatureLayer(PastTracksURL)

df = feature_layer.query(where = "Shape__Length is not null", out_fields = "*", return_geometry=True).sdf
print (df)

## export to shapefile
df.spatial.to_featureclass(hurricane_shp)

print ("Done")

 

RDCOGIS
Occasional Contributor

curious,....now that you are filtering out the bad geometry, can you go back to the .save method, without pandas .sdf

fl = FeatureLayer(_itemUrl)
features = fl.query(where='Shape is not NULL', out_sr=26911)

# save to disk
print('saving the Feature Layer to Shapefile')
features.save(save_location=_pathShps, out_name=_friendlyName + '.shp')

 

0 Kudos