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
Solved! Go to Solution.
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")
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
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'
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
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'
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.
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.
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")
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')